diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index 61f2ce4..5feaedc 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -16,13 +16,13 @@ #include "access/heapam.h" #include "access/transam.h" +#include "catalog/catalog.h" #include "miscadmin.h" #include "pgstat.h" #include "storage/bufmgr.h" #include "utils/rel.h" #include "utils/tqual.h" - /* Working data for heap_page_prune and subroutines */ typedef struct { @@ -72,6 +72,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer, TransactionId OldestXmin) { Page page = BufferGetPage(buffer); Size minfree; + Transactionid CutoffXmin = OldestXmin; /* * Let's see if we really need pruning. @@ -91,6 +92,18 @@ heap_page_prune_opt(Relation relation, Buffer buffer, TransactionId OldestXmin) return; /* + * We choose to set RecentGlobalXmin only for the current database, which + * means we cannot use it to prune shared relations when reading them with + * MVCC snapshots. By making that choice it allows our snapshots to be + * smaller and faster, and the RecentGlobalXmin will be further forward + * and offer better pruning of non-shared relations. So when accessing a + * shared relation and we see the page is prunable (above) we get an + * OldestXmin across all databases. + */ + if (IsSharedRelation(relation->rd_id)) + CutoffXmin = GetOldestXmin(true, true); + + /* * We prune when a previous UPDATE failed to find enough space on the page * for a new tuple version, or when free space falls below the relation's * fill-factor target (but not less than 10%). @@ -124,7 +137,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer, TransactionId OldestXmin) * needed */ /* OK to prune */ - (void) heap_page_prune(relation, buffer, OldestXmin, true, &ignore); + (void) heap_page_prune(relation, buffer, CutoffXmin, true, &ignore); } /* And release buffer lock */ diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 1a48485..60153f4 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -55,6 +55,7 @@ #include "storage/spin.h" #include "utils/builtins.h" #include "utils/snapmgr.h" +#include "utils/tqual.h" /* Our shared memory area */ @@ -1185,6 +1186,8 @@ GetMaxSnapshotSubxidCount(void) * RecentGlobalXmin: the global xmin (oldest TransactionXmin across all * running transactions, except those running LAZY VACUUM). This is * the same computation done by GetOldestXmin(true, true). + * For MVCC snapshots we examine transactions running only in our + * database, ignoring longer running transactions in other databases. * * Note: this function should probably not be called with an argument that's * not statically allocated (see xip allocation below). @@ -1200,9 +1203,12 @@ GetSnapshotData(Snapshot snapshot) int count = 0; int subcount = 0; bool suboverflowed = false; + bool allDbs = false; Assert(snapshot != NULL); + allDbs = !IsMVCCSnapshot(snapshot); + /* * Allocating space for maxProcs xids is usually overkill; numProcs would * be sufficient. But it seems better to do the malloc while not holding @@ -1278,6 +1284,12 @@ GetSnapshotData(Snapshot snapshot) if (proc->vacuumFlags & PROC_IN_VACUUM) continue; + /* MVCC snapshots ignore other databases */ + if (!allDbs && + proc->databaseId != MyDatabaseId && + proc->databaseId != 0) /* always include WalSender */ + continue; + /* Update globalxmin to be the smallest valid xmin */ xid = proc->xmin; /* fetch just once */ if (TransactionIdIsNormal(xid) &&