agora inbox for [email protected]
help / color / mirror / Atom feedRe: grant and SQL92
1926+ messages / 5 participants
[nested] [flat]
* Re: grant and SQL92
@ 2001-07-09 19:57 Bruce Momjian <[email protected]>
2001-07-09 20:20 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
2001-07-09 20:59 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
2001-07-13 16:27 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
0 siblings, 3 replies; 1926+ messages in thread
From: Bruce Momjian @ 2001-07-09 19:57 UTC (permalink / raw)
To: Vince Vielhaber <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; pgsql-hackers
> On Sat, 9 Jun 2001, Peter Eisentraut wrote:
>
> > Vince Vielhaber writes:
> >
> > > I can grant a series of privileges (comma separated) on a series of
> > > objects (comma separated) to either a user, group or public NOT a
> > > comma separated list of users or groups.
> >
> > I should have this finished today to tomorrow.
>
> I looked at it but it looked too much like it involved gram.y which I'm
> going to happily stay away from for now :)
Added to TODO:
* Allow GRANT/REVOKE to handle multiple user/group names
--
Bruce Momjian | http://candle.pha.pa.us
[email protected] | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
@ 2001-07-09 20:20 ` Vince Vielhaber <[email protected]>
2 siblings, 0 replies; 1926+ messages in thread
From: Vince Vielhaber @ 2001-07-09 20:20 UTC (permalink / raw)
To: Bruce Momjian <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; pgsql-hackers
On Mon, 9 Jul 2001, Bruce Momjian wrote:
> > On Sat, 9 Jun 2001, Peter Eisentraut wrote:
> >
> > > Vince Vielhaber writes:
> > >
> > > > I can grant a series of privileges (comma separated) on a series of
> > > > objects (comma separated) to either a user, group or public NOT a
> > > > comma separated list of users or groups.
> > >
> > > I should have this finished today to tomorrow.
> >
> > I looked at it but it looked too much like it involved gram.y which I'm
> > going to happily stay away from for now :)
>
> Added to TODO:
>
> * Allow GRANT/REVOKE to handle multiple user/group names
I'm guessing Peter got sidetracked? If it's still open after I submit
a create user patch (with the help of Tom Lane I'm no longer uncomfortable
with gram.y) I'll take a look at this.
Vince.
--
==========================================================================
Vince Vielhaber -- KA8CSH email: [email protected] http://www.pop4.net
56K Nationwide Dialup from $16.00/mo at Pop4 Networking
Online Campground Directory http://www.camping-usa.com
Online Giftshop Superstore http://www.cloudninegifts.com
==========================================================================
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
@ 2001-07-09 20:59 ` Peter Eisentraut <[email protected]>
2001-07-10 20:34 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
2 siblings, 1 reply; 1926+ messages in thread
From: Peter Eisentraut @ 2001-07-09 20:59 UTC (permalink / raw)
To: Bruce Momjian <[email protected]>; +Cc: Vince Vielhaber <[email protected]>; pgsql-hackers
Bruce Momjian writes:
> > On Sat, 9 Jun 2001, Peter Eisentraut wrote:
> >
> > > Vince Vielhaber writes:
> > >
> > > > I can grant a series of privileges (comma separated) on a series of
> > > > objects (comma separated) to either a user, group or public NOT a
> > > > comma separated list of users or groups.
> > >
> > > I should have this finished today to tomorrow.
> >
> > I looked at it but it looked too much like it involved gram.y which I'm
> > going to happily stay away from for now :)
>
> Added to TODO:
>
> * Allow GRANT/REVOKE to handle multiple user/group names
You must have missed the part about tomorrow.
--
Peter Eisentraut [email protected] http://funkturm.homeip.net/~peter
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-09 20:59 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
@ 2001-07-10 20:34 ` Vince Vielhaber <[email protected]>
2001-07-10 21:15 ` Re: grant and SQL92 Bruce Momjian <[email protected]>
0 siblings, 1 reply; 1926+ messages in thread
From: Vince Vielhaber @ 2001-07-10 20:34 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: Bruce Momjian <[email protected]>; pgsql-hackers
On Mon, 9 Jul 2001, Peter Eisentraut wrote:
> Bruce Momjian writes:
>
> > > On Sat, 9 Jun 2001, Peter Eisentraut wrote:
> > >
> > > > Vince Vielhaber writes:
> > > >
> > > > > I can grant a series of privileges (comma separated) on a series of
> > > > > objects (comma separated) to either a user, group or public NOT a
> > > > > comma separated list of users or groups.
> > > >
> > > > I should have this finished today to tomorrow.
> > >
> > > I looked at it but it looked too much like it involved gram.y which I'm
> > > going to happily stay away from for now :)
> >
> > Added to TODO:
> >
> > * Allow GRANT/REVOKE to handle multiple user/group names
>
> You must have missed the part about tomorrow.
Did you already commit? I was watching for it but could very well
have missed it.
Vince.
--
==========================================================================
Vince Vielhaber -- KA8CSH email: [email protected] http://www.pop4.net
56K Nationwide Dialup from $16.00/mo at Pop4 Networking
Online Campground Directory http://www.camping-usa.com
Online Giftshop Superstore http://www.cloudninegifts.com
==========================================================================
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-09 20:59 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
2001-07-10 20:34 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
@ 2001-07-10 21:15 ` Bruce Momjian <[email protected]>
2001-07-10 21:31 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
2001-07-10 22:47 ` Re: grant and SQL92 Tom Lane <[email protected]>
0 siblings, 2 replies; 1926+ messages in thread
From: Bruce Momjian @ 2001-07-10 21:15 UTC (permalink / raw)
To: Vince Vielhaber <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; pgsql-hackers
> On Mon, 9 Jul 2001, Peter Eisentraut wrote:
>
> > Bruce Momjian writes:
> >
> > > > On Sat, 9 Jun 2001, Peter Eisentraut wrote:
> > > >
> > > > > Vince Vielhaber writes:
> > > > >
> > > > > > I can grant a series of privileges (comma separated) on a series of
> > > > > > objects (comma separated) to either a user, group or public NOT a
> > > > > > comma separated list of users or groups.
> > > > >
> > > > > I should have this finished today to tomorrow.
> > > >
> > > > I looked at it but it looked too much like it involved gram.y which I'm
> > > > going to happily stay away from for now :)
> > >
> > > Added to TODO:
> > >
> > > * Allow GRANT/REVOKE to handle multiple user/group names
> >
> > You must have missed the part about tomorrow.
>
> Did you already commit? I was watching for it but could very well
> have missed it.
I don't see it. The tomorrow Vince was talking about was quite a few
weeks ago. Also, I thought he said he was going to skip it because it
dealt with gram.y. I do have a pending patch from him that arrived
today that deals with the CREATEDB/CREATEUSER ordering. I have not
applied it because it hasn't appeared on patches yet for people to
comment.
--
Bruce Momjian | http://candle.pha.pa.us
[email protected] | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-09 20:59 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
2001-07-10 20:34 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
2001-07-10 21:15 ` Re: grant and SQL92 Bruce Momjian <[email protected]>
@ 2001-07-10 21:31 ` Vince Vielhaber <[email protected]>
2001-07-10 21:33 ` Re: grant and SQL92 Bruce Momjian <[email protected]>
1 sibling, 1 reply; 1926+ messages in thread
From: Vince Vielhaber @ 2001-07-10 21:31 UTC (permalink / raw)
To: Bruce Momjian <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; pgsql-hackers
On Tue, 10 Jul 2001, Bruce Momjian wrote:
> > On Mon, 9 Jul 2001, Peter Eisentraut wrote:
> >
> > > Bruce Momjian writes:
> > >
> > > > > On Sat, 9 Jun 2001, Peter Eisentraut wrote:
> > > > >
> > > > > > Vince Vielhaber writes:
> > > > > >
> > > > > > > I can grant a series of privileges (comma separated) on a series of
> > > > > > > objects (comma separated) to either a user, group or public NOT a
> > > > > > > comma separated list of users or groups.
> > > > > >
> > > > > > I should have this finished today to tomorrow.
> > > > >
> > > > > I looked at it but it looked too much like it involved gram.y which I'm
> > > > > going to happily stay away from for now :)
> > > >
> > > > Added to TODO:
> > > >
> > > > * Allow GRANT/REVOKE to handle multiple user/group names
> > >
> > > You must have missed the part about tomorrow.
> >
> > Did you already commit? I was watching for it but could very well
> > have missed it.
>
> I don't see it. The tomorrow Vince was talking about was quite a few
> weeks ago. Also, I thought he said he was going to skip it because it
> dealt with gram.y. I do have a pending patch from him that arrived
> today that deals with the CREATEDB/CREATEUSER ordering. I have not
> applied it because it hasn't appeared on patches yet for people to
> comment.
That was Peter saying he was going to have it finished 'today or
tomorrow'. gram.y wasn't as bad as it at first looked as evidenced
by the patch I submitted today.
Vince.
--
==========================================================================
Vince Vielhaber -- KA8CSH email: [email protected] http://www.pop4.net
56K Nationwide Dialup from $16.00/mo at Pop4 Networking
Online Campground Directory http://www.camping-usa.com
Online Giftshop Superstore http://www.cloudninegifts.com
==========================================================================
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-09 20:59 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
2001-07-10 20:34 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
2001-07-10 21:15 ` Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-10 21:31 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
@ 2001-07-10 21:33 ` Bruce Momjian <[email protected]>
2001-07-10 21:33 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
0 siblings, 1 reply; 1926+ messages in thread
From: Bruce Momjian @ 2001-07-10 21:33 UTC (permalink / raw)
To: Vince Vielhaber <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; pgsql-hackers
> > > > > Added to TODO:
> > > > >
> > > > > * Allow GRANT/REVOKE to handle multiple user/group names
> > > >
> > > > You must have missed the part about tomorrow.
> > >
> > > Did you already commit? I was watching for it but could very well
> > > have missed it.
> >
> > I don't see it. The tomorrow Vince was talking about was quite a few
> > weeks ago. Also, I thought he said he was going to skip it because it
> > dealt with gram.y. I do have a pending patch from him that arrived
> > today that deals with the CREATEDB/CREATEUSER ordering. I have not
> > applied it because it hasn't appeared on patches yet for people to
> > comment.
>
> That was Peter saying he was going to have it finished 'today or
> tomorrow'. gram.y wasn't as bad as it at first looked as evidenced
> by the patch I submitted today.
Oh, sorry. OK.
Yes, that was a sizable patch!
--
Bruce Momjian | http://candle.pha.pa.us
[email protected] | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-09 20:59 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
2001-07-10 20:34 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
2001-07-10 21:15 ` Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-10 21:31 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
2001-07-10 21:33 ` Re: grant and SQL92 Bruce Momjian <[email protected]>
@ 2001-07-10 21:33 ` Vince Vielhaber <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Vince Vielhaber @ 2001-07-10 21:33 UTC (permalink / raw)
To: Bruce Momjian <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; pgsql-hackers
On Tue, 10 Jul 2001, Bruce Momjian wrote:
> > > > > > Added to TODO:
> > > > > >
> > > > > > * Allow GRANT/REVOKE to handle multiple user/group names
> > > > >
> > > > > You must have missed the part about tomorrow.
> > > >
> > > > Did you already commit? I was watching for it but could very well
> > > > have missed it.
> > >
> > > I don't see it. The tomorrow Vince was talking about was quite a few
> > > weeks ago. Also, I thought he said he was going to skip it because it
> > > dealt with gram.y. I do have a pending patch from him that arrived
> > > today that deals with the CREATEDB/CREATEUSER ordering. I have not
> > > applied it because it hasn't appeared on patches yet for people to
> > > comment.
> >
> > That was Peter saying he was going to have it finished 'today or
> > tomorrow'. gram.y wasn't as bad as it at first looked as evidenced
> > by the patch I submitted today.
>
> Oh, sorry. OK.
>
> Yes, that was a sizable patch!
It's a sizable change :)
Vince.
--
==========================================================================
Vince Vielhaber -- KA8CSH email: [email protected] http://www.pop4.net
56K Nationwide Dialup from $16.00/mo at Pop4 Networking
Online Campground Directory http://www.camping-usa.com
Online Giftshop Superstore http://www.cloudninegifts.com
==========================================================================
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-09 20:59 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
2001-07-10 20:34 ` Re: grant and SQL92 Vince Vielhaber <[email protected]>
2001-07-10 21:15 ` Re: grant and SQL92 Bruce Momjian <[email protected]>
@ 2001-07-10 22:47 ` Tom Lane <[email protected]>
1 sibling, 0 replies; 1926+ messages in thread
From: Tom Lane @ 2001-07-10 22:47 UTC (permalink / raw)
To: Bruce Momjian <[email protected]>; +Cc: Vince Vielhaber <[email protected]>; Peter Eisentraut <[email protected]>; pgsql-hackers
Bruce Momjian <[email protected]> writes:
> I do have a pending patch from him that arrived
> today that deals with the CREATEDB/CREATEUSER ordering. I have not
> applied it because it hasn't appeared on patches yet for people to
> comment.
I already applied his CREATE/ALTER USER patch, because he'd passed it by
me for review several times previously (I forget if any of that mail was
cc'd to the lists). I had some other changes to make in the same files
and figured it might as well go in all at once instead of risking merge
problems.
AFAIK, no one has touched the GRANT/REVOKE issue yet.
regards, tom lane
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
@ 2001-07-13 16:27 ` Peter Eisentraut <[email protected]>
2001-07-13 16:37 ` Re: grant and SQL92 Bruce Momjian <[email protected]>
2 siblings, 1 reply; 1926+ messages in thread
From: Peter Eisentraut @ 2001-07-13 16:27 UTC (permalink / raw)
To: Bruce Momjian <[email protected]>; +Cc: Vince Vielhaber <[email protected]>; pgsql-hackers
Bruce Momjian writes:
> > On Sat, 9 Jun 2001, Peter Eisentraut wrote:
> >
> > > Vince Vielhaber writes:
> > >
> > > > I can grant a series of privileges (comma separated) on a series of
> > > > objects (comma separated) to either a user, group or public NOT a
> > > > comma separated list of users or groups.
> > >
> > > I should have this finished today to tomorrow.
> >
> > I looked at it but it looked too much like it involved gram.y which I'm
> > going to happily stay away from for now :)
>
> Added to TODO:
>
> * Allow GRANT/REVOKE to handle multiple user/group names
You're still not getting that part about tomorrow. ;-)
--
Peter Eisentraut [email protected] http://funkturm.homeip.net/~peter
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-13 16:27 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
@ 2001-07-13 16:37 ` Bruce Momjian <[email protected]>
2001-07-13 18:22 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
0 siblings, 1 reply; 1926+ messages in thread
From: Bruce Momjian @ 2001-07-13 16:37 UTC (permalink / raw)
To: Peter Eisentraut <[email protected]>; +Cc: Vince Vielhaber <[email protected]>; pgsql-hackers
> Bruce Momjian writes:
>
> > > On Sat, 9 Jun 2001, Peter Eisentraut wrote:
> > >
> > > > Vince Vielhaber writes:
> > > >
> > > > > I can grant a series of privileges (comma separated) on a series of
> > > > > objects (comma separated) to either a user, group or public NOT a
> > > > > comma separated list of users or groups.
> > > >
> > > > I should have this finished today to tomorrow.
> > >
> > > I looked at it but it looked too much like it involved gram.y which I'm
> > > going to happily stay away from for now :)
> >
> > Added to TODO:
> >
> > * Allow GRANT/REVOKE to handle multiple user/group names
>
> You're still not getting that part about tomorrow. ;-)
Can't I keep it on the TODO until it is done? And wasn't yesterday
tomorrow? :-)
--
Bruce Momjian | http://candle.pha.pa.us
[email protected] | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
^ permalink raw reply [nested|flat] 1926+ messages in thread
* Re: grant and SQL92
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-13 16:27 ` Re: grant and SQL92 Peter Eisentraut <[email protected]>
2001-07-13 16:37 ` Re: grant and SQL92 Bruce Momjian <[email protected]>
@ 2001-07-13 18:22 ` Peter Eisentraut <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Peter Eisentraut @ 2001-07-13 18:22 UTC (permalink / raw)
To: Bruce Momjian <[email protected]>; +Cc: Vince Vielhaber <[email protected]>; pgsql-hackers
Bruce Momjian writes:
> Can't I keep it on the TODO until it is done? And wasn't yesterday
> tomorrow? :-)
No, tomorrow was the day after June 9th.
--
Peter Eisentraut [email protected] http://funkturm.homeip.net/~peter
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1926+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1926+ messages in thread
end of thread, other threads:[~2026-05-06 07:38 UTC | newest]
Thread overview: 1926+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2001-07-09 19:57 Re: grant and SQL92 Bruce Momjian <[email protected]>
2001-07-09 20:20 ` Vince Vielhaber <[email protected]>
2001-07-09 20:59 ` Peter Eisentraut <[email protected]>
2001-07-10 20:34 ` Vince Vielhaber <[email protected]>
2001-07-10 21:15 ` Bruce Momjian <[email protected]>
2001-07-10 21:31 ` Vince Vielhaber <[email protected]>
2001-07-10 21:33 ` Bruce Momjian <[email protected]>
2001-07-10 21:33 ` Vince Vielhaber <[email protected]>
2001-07-10 22:47 ` Tom Lane <[email protected]>
2001-07-13 16:27 ` Peter Eisentraut <[email protected]>
2001-07-13 16:37 ` Bruce Momjian <[email protected]>
2001-07-13 18:22 ` Peter Eisentraut <[email protected]>
2026-05-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 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 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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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 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 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 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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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 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 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 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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-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 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] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07: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]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox