Optimize GetConflictingVirtualXIDs() in roughly the same manner we
optimize TransactionIdIsInProgress().
Views?
--
Simon Riggs www.2ndQuadrant.com
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 12de877..7f9b10e 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -1686,12 +1686,21 @@ GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0,
* this array sufficiently often that we use malloc for the result.
*/
VirtualTransactionId *
-GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid)
+GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid, int *return_count)
{
static VirtualTransactionId *vxids;
ProcArrayStruct *arrayP = procArray;
int count = 0;
int index;
+ TransactionId globalxmin;
+
+ /*
+ * Don't bother checking a valid TransactionId older than RecentGlobalXmin;
+ * it could not possibly cause a conflict.
+ */
+ if (TransactionIdPrecedes(limitXmin, RecentGlobalXmin) &&
+ TransactionIdIsValid(limitXmin))
+ return NULL;
/*
* If not first time through, get workspace to remember main XIDs in. We
@@ -1717,19 +1726,28 @@ GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid)
if (!TransactionIdIsValid(limitXmin))
limitXmin = ShmemVariableCache->latestCompletedXid;
+ globalxmin = ShmemVariableCache->latestCompletedXid;
+
for (index = 0; index < arrayP->numProcs; index++)
{
volatile PGPROC *proc = arrayP->procs[index];
+ TransactionId pxmin;
/* Exclude prepared transactions */
if (proc->pid == 0)
continue;
+ /* Fetch xmin just once - can't change on us, but good coding */
+ pxmin = proc->xmin;
+
+ /* Update globalxmin to be the smallest valid xmin */
+ if (TransactionIdIsNormal(pxmin) &&
+ TransactionIdPrecedes(pxmin, globalxmin))
+ globalxmin = pxmin;
+
if (!OidIsValid(dbOid) ||
proc->databaseId == dbOid)
{
- /* Fetch xmin just once - can't change on us, but good coding */
- TransactionId pxmin = proc->xmin;
/*
* We ignore an invalid pxmin because this means that backend
@@ -1748,6 +1766,10 @@ GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid)
LWLockRelease(ProcArrayLock);
+ RecentGlobalXmin = globalxmin;
+
+ *return_count = count;
+
/* add the terminator */
vxids[count].backendId = InvalidBackendId;
vxids[count].localTransactionId = InvalidLocalTransactionId;
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index c8fde2f..ea9c2e3 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -244,11 +244,12 @@ void
ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid, RelFileNode node)
{
VirtualTransactionId *backends;
+ int conflicts = 0;
backends = GetConflictingVirtualXIDs(latestRemovedXid,
- node.dbNode);
-
- ResolveRecoveryConflictWithVirtualXIDs(backends,
+ node.dbNode, &conflicts);
+ if (conflicts > 0)
+ ResolveRecoveryConflictWithVirtualXIDs(backends,
PROCSIG_RECOVERY_CONFLICT_SNAPSHOT);
}
@@ -256,6 +257,7 @@ void
ResolveRecoveryConflictWithTablespace(Oid tsid)
{
VirtualTransactionId *temp_file_users;
+ int conflicts = 0;
/*
* Standby users may be currently using this tablespace for
@@ -277,7 +279,7 @@ ResolveRecoveryConflictWithTablespace(Oid tsid)
* non-transactional.
*/
temp_file_users = GetConflictingVirtualXIDs(InvalidTransactionId,
- InvalidOid);
+ InvalidOid, &conflicts);
ResolveRecoveryConflictWithVirtualXIDs(temp_file_users,
PROCSIG_RECOVERY_CONFLICT_TABLESPACE);
}
@@ -333,8 +335,9 @@ ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid)
backends = GetLockConflicts(&locktag, AccessExclusiveLock);
else
{
+ int conflicts = 0;
backends = GetConflictingVirtualXIDs(InvalidTransactionId,
- InvalidOid);
+ InvalidOid, &conflicts);
report_memory_error = true;
}
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index 5a026e9..e01ad79 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -57,7 +57,8 @@ extern bool IsBackendPid(int pid);
extern VirtualTransactionId *GetCurrentVirtualXIDs(TransactionId limitXmin,
bool excludeXmin0, bool allDbs, int excludeVacuum,
int *nvxids);
-extern VirtualTransactionId *GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid);
+extern VirtualTransactionId *GetConflictingVirtualXIDs(TransactionId limitXmin,
+ Oid dbOid, int *return_count);
extern pid_t CancelVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode);
extern int CountActiveBackends(void);
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers