aboutsummaryrefslogtreecommitdiff
path: root/contrib/pg_visibility/pg_visibility.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pg_visibility/pg_visibility.c')
-rw-r--r--contrib/pg_visibility/pg_visibility.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index 1a1a4ff7be7..773ba92e454 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -546,11 +546,21 @@ collect_visibility_data(Oid relid, bool include_pd)
*
* 1. Ignore processes xmin's, because they consider connection to other
* databases that were ignored before.
- * 2. Ignore KnownAssignedXids, because they are not database-aware. At the
- * same time, the primary could compute its horizons database-aware.
+ * 2. Ignore KnownAssignedXids, as they are not database-aware. Although we
+ * now perform minimal checking on a standby by always using nextXid, this
+ * approach is better than nothing and will at least catch extremely broken
+ * cases where a xid is in the future.
* 3. Ignore walsender xmin, because it could go backward if some replication
* connections don't use replication slots.
*
+ * While it might seem like we could use KnownAssignedXids for shared
+ * catalogs, since shared catalogs rely on a global horizon rather than a
+ * database-specific one - there are potential edge cases. For example, a
+ * transaction may crash on the primary without writing a commit/abort record.
+ * This would lead to a situation where it appears to still be running on the
+ * standby, even though it has already ended on the primary. For this reason,
+ * it's safer to ignore KnownAssignedXids, even for shared catalogs.
+ *
* As a result, we're using only currently running xids to compute the horizon.
* Surely these would significantly sacrifice accuracy. But we have to do so
* to avoid reporting false errors.
@@ -560,7 +570,17 @@ GetStrictOldestNonRemovableTransactionId(Relation rel)
{
RunningTransactions runningTransactions;
- if (rel == NULL || rel->rd_rel->relisshared || RecoveryInProgress())
+ if (RecoveryInProgress())
+ {
+ TransactionId result;
+
+ /* As we ignore KnownAssignedXids on standby, just pick nextXid */
+ LWLockAcquire(XidGenLock, LW_SHARED);
+ result = XidFromFullTransactionId(TransamVariables->nextXid);
+ LWLockRelease(XidGenLock);
+ return result;
+ }
+ else if (rel == NULL || rel->rd_rel->relisshared)
{
/* Shared relation: take into account all running xids */
runningTransactions = GetRunningTransactionData();