aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/heap/heapam_visibility.c
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2020-08-14 12:15:38 -0700
committerAndres Freund <andres@anarazel.de>2020-08-14 15:33:35 -0700
commit941697c3c1ae5d6ee153065adb96e1e63ee11224 (patch)
tree7a81a69bcec132293286fe3867da82a2a754292e /src/backend/access/heap/heapam_visibility.c
parent2ba5b2db7943742e100834d99548c5d2661a105b (diff)
downloadpostgresql-941697c3c1ae5d6ee153065adb96e1e63ee11224.tar.gz
postgresql-941697c3c1ae5d6ee153065adb96e1e63ee11224.zip
snapshot scalability: Introduce dense array of in-progress xids.
The new array contains the xids for all connected backends / in-use PGPROC entries in a dense manner (in contrast to the PGPROC/PGXACT arrays which can have unused entries interspersed). This improves performance because GetSnapshotData() always needs to scan the xids of all live procarray entries and now there's no need to go through the procArray->pgprocnos indirection anymore. As the set of running top-level xids changes rarely, compared to the number of snapshots taken, this substantially increases the likelihood of most data required for a snapshot being in l2 cache. In read-mostly workloads scanning the xids[] array will sufficient to build a snapshot, as most backends will not have an xid assigned. To keep the xid array dense ProcArrayRemove() needs to move entries behind the to-be-removed proc's one further up in the array. Obviously moving array entries cannot happen while a backend sets it xid. I.e. locking needs to prevent that array entries are moved while a backend modifies its xid. To avoid locking ProcArrayLock in GetNewTransactionId() - a fairly hot spot already - ProcArrayAdd() / ProcArrayRemove() now needs to hold XidGenLock in addition to ProcArrayLock. Adding / Removing a procarray entry is not a very frequent operation, even taking 2PC into account. Due to the above, the dense array entries can only be read or modified while holding ProcArrayLock and/or XidGenLock. This prevents a concurrent ProcArrayRemove() from shifting the dense array while it is accessed concurrently. While the new dense array is very good when needing to look at all xids it is less suitable when accessing a single backend's xid. In particular it would be problematic to have to acquire a lock to access a backend's own xid. Therefore a backend's xid is not just stored in the dense array, but also in PGPROC. This also allows a backend to only access the shared xid value when the backend had acquired an xid. The infrastructure added in this commit will be used for the remaining PGXACT fields in subsequent commits. They are kept separate to make review easier. Author: Andres Freund <andres@anarazel.de> Reviewed-By: Robert Haas <robertmhaas@gmail.com> Reviewed-By: Thomas Munro <thomas.munro@gmail.com> Reviewed-By: David Rowley <dgrowleyml@gmail.com> Discussion: https://postgr.es/m/20200301083601.ews6hz5dduc3w2se@alap3.anarazel.de
Diffstat (limited to 'src/backend/access/heap/heapam_visibility.c')
-rw-r--r--src/backend/access/heap/heapam_visibility.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/src/backend/access/heap/heapam_visibility.c b/src/backend/access/heap/heapam_visibility.c
index 528e75bafd4..80bd4940769 100644
--- a/src/backend/access/heap/heapam_visibility.c
+++ b/src/backend/access/heap/heapam_visibility.c
@@ -11,12 +11,12 @@
* shared buffer content lock on the buffer containing the tuple.
*
* NOTE: When using a non-MVCC snapshot, we must check
- * TransactionIdIsInProgress (which looks in the PGXACT array)
+ * TransactionIdIsInProgress (which looks in the PGPROC array)
* before TransactionIdDidCommit/TransactionIdDidAbort (which look in
* pg_xact). Otherwise we have a race condition: we might decide that a
* just-committed transaction crashed, because none of the tests succeed.
* xact.c is careful to record commit/abort in pg_xact before it unsets
- * MyPgXact->xid in the PGXACT array. That fixes that problem, but it
+ * MyProc->xid in the PGPROC array. That fixes that problem, but it
* also means there is a window where TransactionIdIsInProgress and
* TransactionIdDidCommit will both return true. If we check only
* TransactionIdDidCommit, we could consider a tuple committed when a
@@ -956,7 +956,7 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
* coding where we tried to set the hint bits as soon as possible, we instead
* did TransactionIdIsInProgress in each call --- to no avail, as long as the
* inserting/deleting transaction was still running --- which was more cycles
- * and more contention on the PGXACT array.
+ * and more contention on ProcArrayLock.
*/
static bool
HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot,
@@ -1459,7 +1459,7 @@ HeapTupleSatisfiesNonVacuumable(HeapTuple htup, Snapshot snapshot,
* HeapTupleSatisfiesMVCC) and, therefore, any hint bits that can be set
* should already be set. We assume that if no hint bits are set, the xmin
* or xmax transaction is still running. This is therefore faster than
- * HeapTupleSatisfiesVacuum, because we don't consult PGXACT nor CLOG.
+ * HeapTupleSatisfiesVacuum, because we consult neither procarray nor CLOG.
* It's okay to return false when in doubt, but we must return true only
* if the tuple is removable.
*/