agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH v1 3/4] autovac: combine reloptions correctly 111+ messages / 2 participants [nested] [flat]
* [PATCH v1 3/4] autovac: combine reloptions correctly @ 2025-06-23 20:16 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Nathan Bossart @ 2025-06-23 20:16 UTC (permalink / raw) --- src/backend/postmaster/autovacuum.c | 85 +++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 3bedca971ff..0d1f4e38b58 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -1873,6 +1873,73 @@ get_database_list(void) return dblist; } +static void +combine_relopts(StdRdOptions *toast_opts, const StdRdOptions *main_opts) +{ + AutoVacOpts *toast_avopts = &toast_opts->autovacuum; + const AutoVacOpts *main_avopts = &main_opts->autovacuum; + + /* XXX: need isset_offset to combine "enabled" */ + + if (toast_avopts->vacuum_threshold == -1) + toast_avopts->vacuum_threshold = main_avopts->vacuum_threshold; + + if (toast_avopts->vacuum_max_threshold == -2) + toast_avopts->vacuum_max_threshold = main_avopts->vacuum_max_threshold; + + if (toast_avopts->vacuum_ins_threshold == -2) + toast_avopts->vacuum_ins_threshold = main_avopts->vacuum_ins_threshold; + + if (toast_avopts->analyze_threshold == -1) + toast_avopts->analyze_threshold = main_avopts->analyze_threshold; + + if (toast_avopts->vacuum_cost_limit == -1) + toast_avopts->vacuum_cost_limit = main_avopts->vacuum_cost_limit; + + if (toast_avopts->freeze_min_age == -1) + toast_avopts->freeze_min_age = main_avopts->freeze_min_age; + + if (toast_avopts->freeze_max_age == -1) + toast_avopts->freeze_max_age = main_avopts->freeze_max_age; + + if (toast_avopts->freeze_table_age == -1) + toast_avopts->freeze_table_age = main_avopts->freeze_table_age; + + if (toast_avopts->multixact_freeze_min_age == -1) + toast_avopts->multixact_freeze_min_age = main_avopts->multixact_freeze_min_age; + + if (toast_avopts->multixact_freeze_max_age == -1) + toast_avopts->multixact_freeze_max_age = main_avopts->multixact_freeze_max_age; + + if (toast_avopts->multixact_freeze_table_age == -1) + toast_avopts->multixact_freeze_table_age = main_avopts->multixact_freeze_table_age; + + /* XXX: need isset_offset for log_min_duration */ + + if (toast_avopts->vacuum_cost_delay == -1) + toast_avopts->vacuum_cost_delay = main_avopts->vacuum_cost_delay; + + if (toast_avopts->vacuum_scale_factor == -1) + toast_avopts->vacuum_scale_factor = main_avopts->vacuum_scale_factor; + + if (toast_avopts->vacuum_ins_scale_factor == -1) + toast_avopts->vacuum_ins_scale_factor = main_avopts->vacuum_ins_scale_factor; + + if (toast_avopts->analyze_scale_factor == -1) + toast_avopts->analyze_scale_factor = main_avopts->analyze_scale_factor; + + /* XXX: need isset_offset for vacuum_index_cleanup */ + + if (!toast_opts->vacuum_truncate_set && main_opts->vacuum_truncate_set) + { + toast_opts->vacuum_truncate = main_opts->vacuum_truncate; + toast_opts->vacuum_truncate_set = true; + } + + if (toast_opts->vacuum_max_eager_freeze_failure_rate == -1) + toast_opts->vacuum_max_eager_freeze_failure_rate = main_opts->vacuum_max_eager_freeze_failure_rate; +} + /* * Process a database table-by-table * @@ -2113,7 +2180,16 @@ do_autovacuum(void) */ relopts = (StdRdOptions *) extractRelOptions(tuple, pg_class_desc, NULL); if (relopts) + { + av_relation *hentry; + bool found; + free_relopts = true; + + hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); + if (found && hentry->ar_hasrelopts) + combine_relopts(relopts, &hentry->ar_reloptions); + } else { av_relation *hentry; @@ -2733,7 +2809,16 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, */ relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) + { + av_relation *hentry; + bool found; + free_relopts = true; + + hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); + if (found && hentry->ar_hasrelopts) + combine_relopts(relopts, &hentry->ar_reloptions); + } else if (classForm->relkind == RELKIND_TOASTVALUE && table_toast_map != NULL) { -- 2.39.5 (Apple Git-154) --QWBYbd5Ar5k8NvSv Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v1-0004-combine-relopts-correctly-for-VACUUM-commands.patch ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 111+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 111+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 111+ messages in thread
end of thread, other threads:[~2026-05-06 07:38 UTC | newest] Thread overview: 111+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2025-06-23 20:16 [PATCH v1 3/4] autovac: combine reloptions correctly Nathan Bossart <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox