mirror of
https://github.com/postgres/postgres.git
synced 2025-11-26 23:43:30 +03:00
Move isolationtester's is-blocked query into C code for speed.
Commit 4deb41381 modified isolationtester's query to see whether a
session is blocked to also check for waits occurring in GetSafeSnapshot.
However, it did that in a way that enormously increased the query's
runtime under CLOBBER_CACHE_ALWAYS, causing the buildfarm members
that use that to run about four times slower than before, and in some
cases fail entirely. To fix, push the entire logic into a dedicated
backend function. This should actually reduce the CLOBBER_CACHE_ALWAYS
runtime from what it was previously, though I've not checked that.
In passing, expose a SQL function to check for safe-snapshot blockage,
comparable to pg_blocking_pids. This is more or less free given the
infrastructure built to solve the other problem, so we might as well.
Thomas Munro
Discussion: https://postgr.es/m/20170407165749.pstcakbc637opkax@alap3.anarazel.de
This commit is contained in:
@@ -1555,6 +1555,56 @@ GetSafeSnapshot(Snapshot origSnapshot)
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
/*
|
||||
* GetSafeSnapshotBlockingPids
|
||||
* If the specified process is currently blocked in GetSafeSnapshot,
|
||||
* write the process IDs of all processes that it is blocked by
|
||||
* into the caller-supplied buffer output[]. The list is truncated at
|
||||
* output_size, and the number of PIDs written into the buffer is
|
||||
* returned. Returns zero if the given PID is not currently blocked
|
||||
* in GetSafeSnapshot.
|
||||
*/
|
||||
int
|
||||
GetSafeSnapshotBlockingPids(int blocked_pid, int *output, int output_size)
|
||||
{
|
||||
int num_written = 0;
|
||||
SERIALIZABLEXACT *sxact;
|
||||
|
||||
LWLockAcquire(SerializableXactHashLock, LW_SHARED);
|
||||
|
||||
/* Find blocked_pid's SERIALIZABLEXACT by linear search. */
|
||||
for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact))
|
||||
{
|
||||
if (sxact->pid == blocked_pid)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Did we find it, and is it currently waiting in GetSafeSnapshot? */
|
||||
if (sxact != NULL && SxactIsDeferrableWaiting(sxact))
|
||||
{
|
||||
RWConflict possibleUnsafeConflict;
|
||||
|
||||
/* Traverse the list of possible unsafe conflicts collecting PIDs. */
|
||||
possibleUnsafeConflict = (RWConflict)
|
||||
SHMQueueNext(&sxact->possibleUnsafeConflicts,
|
||||
&sxact->possibleUnsafeConflicts,
|
||||
offsetof(RWConflictData, inLink));
|
||||
|
||||
while (possibleUnsafeConflict != NULL && num_written < output_size)
|
||||
{
|
||||
output[num_written++] = possibleUnsafeConflict->sxactOut->pid;
|
||||
possibleUnsafeConflict = (RWConflict)
|
||||
SHMQueueNext(&sxact->possibleUnsafeConflicts,
|
||||
&possibleUnsafeConflict->inLink,
|
||||
offsetof(RWConflictData, inLink));
|
||||
}
|
||||
}
|
||||
|
||||
LWLockRelease(SerializableXactHashLock);
|
||||
|
||||
return num_written;
|
||||
}
|
||||
|
||||
/*
|
||||
* Acquire a snapshot that can be used for the current transaction.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user