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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers