agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH v3] decode XACT_ASSIGNMENT while building snapshot 138+ messages / 3 participants [nested] [flat]
* [PATCH v3] decode XACT_ASSIGNMENT while building snapshot @ 2019-07-26 22:38 Alvaro Herrera <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Alvaro Herrera @ 2019-07-26 22:38 UTC (permalink / raw) --- src/backend/replication/logical/decode.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c index 151c3ef882..a6f7dc2723 100644 --- a/src/backend/replication/logical/decode.c +++ b/src/backend/replication/logical/decode.c @@ -215,14 +215,19 @@ DecodeXactOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) ReorderBuffer *reorder = ctx->reorder; XLogReaderState *r = buf->record; uint8 info = XLogRecGetInfo(r) & XLOG_XACT_OPMASK; + SnapBuildState state; /* - * No point in doing anything yet, data could not be decoded anyway. It's - * ok not to call ReorderBufferProcessXid() in that case, except in the - * assignment case there'll not be any later records with the same xid; - * and in the assignment case we'll not decode those xacts. + * If the snapshot isn't yet fully built, we cannot decode anything, so + * bail out. + * + * However, it's critical to process XLOG_XACT_ASSIGNMENT records even + * when the snapshot is being built: it is possible to get later records + * that require subxids to be properly assigned. */ - if (SnapBuildCurrentState(builder) < SNAPBUILD_FULL_SNAPSHOT) + state = SnapBuildCurrentState(builder); + if (state < SNAPBUILD_FULL_SNAPSHOT || + (info == XLOG_XACT_ASSIGNMENT && state < SNAPBUILD_BUILDING_SNAPSHOT)) return; switch (info) -- 2.17.1 --3MwIy2ne0vdjdPXF-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH v2 2/2] fix pg_stat_get_backend_subxact to use real backend id @ 2023-08-24 14:58 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Nathan Bossart @ 2023-08-24 14:58 UTC (permalink / raw) --- src/backend/utils/activity/backend_status.c | 36 +++++++++++++++------ src/backend/utils/adt/pgstatfuncs.c | 2 +- src/include/utils/backend_status.h | 1 + 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c index aea05a9014..d5babd9fb0 100644 --- a/src/backend/utils/activity/backend_status.c +++ b/src/backend/utils/activity/backend_status.c @@ -1088,9 +1088,33 @@ cmp_lbestatus(const void *a, const void *b) */ PgBackendStatus * pgstat_get_beentry_by_backend_id(BackendId beid) +{ + LocalPgBackendStatus *ret = pgstat_get_local_beentry_by_backend_id(beid); + + if (ret) + return &ret->backendStatus; + + return NULL; +} + + +/* ---------- + * pgstat_get_local_beentry_by_backend_id() - + * + * Like pgstat_get_beentry_by_backend_id() but with locally computed additions + * (like xid and xmin values of the backend) + * + * The beid argument is the BackendId of the desired session + * (note that this is unlike pgstat_get_local_beentry_by_index()). + * + * NB: caller is responsible for checking if the user is permitted to see this + * info (especially the querystring). + * ---------- + */ +LocalPgBackendStatus * +pgstat_get_local_beentry_by_backend_id(BackendId beid) { LocalPgBackendStatus key; - LocalPgBackendStatus *ret; pgstat_read_current_status(); @@ -1099,14 +1123,8 @@ pgstat_get_beentry_by_backend_id(BackendId beid) * bsearch() to search it efficiently. */ key.backend_id = beid; - ret = (LocalPgBackendStatus *) bsearch(&key, localBackendStatusTable, - localNumBackends, - sizeof(LocalPgBackendStatus), - cmp_lbestatus); - if (ret) - return &ret->backendStatus; - - return NULL; + return bsearch(&key, localBackendStatusTable, localNumBackends, + sizeof(LocalPgBackendStatus), cmp_lbestatus); } diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 7deefed5ab..62d327bb92 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -727,7 +727,7 @@ pg_stat_get_backend_subxact(PG_FUNCTION_ARGS) BlessTupleDesc(tupdesc); - if ((local_beentry = pgstat_get_local_beentry_by_index(beid)) != NULL) + if ((local_beentry = pgstat_get_local_beentry_by_backend_id(beid)) != NULL) { /* Fill values and NULLs */ values[0] = Int32GetDatum(local_beentry->backend_subxact_count); diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h index e53098ec9e..a996c7fd23 100644 --- a/src/include/utils/backend_status.h +++ b/src/include/utils/backend_status.h @@ -334,6 +334,7 @@ extern uint64 pgstat_get_my_query_id(void); */ extern int pgstat_fetch_stat_numbackends(void); extern PgBackendStatus *pgstat_get_beentry_by_backend_id(BackendId beid); +extern LocalPgBackendStatus *pgstat_get_local_beentry_by_backend_id(BackendId beid); extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int beid); extern char *pgstat_clip_activity(const char *raw_activity); -- 2.25.1 --gKMricLos+KVdGMg-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 138+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 138+ messages in thread
end of thread, other threads:[~2026-05-06 07:38 UTC | newest] Thread overview: 138+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2019-07-26 22:38 [PATCH v3] decode XACT_ASSIGNMENT while building snapshot Alvaro Herrera <[email protected]> 2023-08-24 14:58 [PATCH v2 2/2] fix pg_stat_get_backend_subxact to use real backend id Nathan Bossart <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox