agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH 3/3] Distinguish properly when database-specific transaction list should be used. 545+ messages / 2 participants [nested] [flat]
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 545+ messages in thread
* [PATCH va1 1/2] WIP: Use permanent FunctionCallInfo in printtup @ 2026-05-06 15:41 Andres Freund <[email protected]> 0 siblings, 0 replies; 545+ messages in thread From: Andres Freund @ 2026-05-06 15:41 UTC (permalink / raw) Should probably be done similarly for COPY --- src/backend/access/common/printtup.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index 616bdafd395..6fa93a6798a 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -50,6 +50,8 @@ typedef struct bool typisvarlena; /* is it varlena (ie possibly toastable)? */ int16 format; /* format code for this column */ FmgrInfo finfo; /* Precomputed call info for output fn */ + /* XXX: Would probably be faster to allocate "inline" */ + FunctionCallInfo outstate; /* Prepared FCI for slightly faster calls */ } PrinttupAttrInfo; typedef struct @@ -291,6 +293,10 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unsupported format code: %d", format))); + + /* both out and send funcs have one argument */ + thisState->outstate = palloc0(SizeForFunctionCallInfo(1)); + thisState->outstate->flinfo = &thisState->finfo; } } @@ -353,12 +359,16 @@ printtup(TupleTableSlot *slot, DestReceiver *self) VALGRIND_CHECK_MEM_IS_DEFINED(DatumGetPointer(attr), VARSIZE_ANY(DatumGetPointer(attr))); + /* fill in argument for output / send function */ + thisState->outstate->args[0].value = attr; + if (thisState->format == 0) { /* Text output */ char *outputstr; - outputstr = OutputFunctionCall(&thisState->finfo, attr); + outputstr = DatumGetCString(FunctionCallInvoke(thisState->outstate)); + Assert(!thisState->outstate->isnull); pq_sendcountedtext(buf, outputstr, strlen(outputstr)); } else @@ -366,7 +376,8 @@ printtup(TupleTableSlot *slot, DestReceiver *self) /* Binary output */ bytea *outputbytes; - outputbytes = SendFunctionCall(&thisState->finfo, attr); + outputbytes = DatumGetByteaP(FunctionCallInvoke(thisState->outstate)); + Assert(!thisState->outstate->isnull); pq_sendint32(buf, VARSIZE(outputbytes) - VARHDRSZ); pq_sendbytes(buf, VARDATA(outputbytes), VARSIZE(outputbytes) - VARHDRSZ); -- 2.46.0.519.g2e7b89e038 --benhmb75h34eqzc4 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="va1-0002-Mega-WIP-Optimized-out-send-path-for-printtup.patch" ^ permalink raw reply [nested|flat] 545+ messages in thread
end of thread, other threads:[~2026-05-06 15:41 UTC | newest] Thread overview: 545+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 15:41 [PATCH va1 1/2] WIP: Use permanent FunctionCallInfo in printtup Andres Freund <[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