Acquire ProcArrayLock exclusively in ProcArrayClearTransaction.
authorAndres Freund <andres@anarazel.de>
Thu, 20 Aug 2020 01:19:52 +0000 (18:19 -0700)
committerAndres Freund <andres@anarazel.de>
Thu, 20 Aug 2020 01:24:33 +0000 (18:24 -0700)
This corrects an oversight by me in 20729324078, which made
ProcArrayClearTransaction() increment xactCompletionCount. That requires an
exclusive lock, obviously.

There's other approaches that avoid the exclusive acquisition, but given that a
2PC commit is fairly heavyweight, it doesn't seem worth doing so. I've not been
able to measure a performance difference, unsurprisingly.  I did add a
comment documenting that we could do so, should it ever become a bottleneck.

Reported-By: Tom Lane <tgl@sss.pgh.pa.us>
Author: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/1355915.1597794204@sss.pgh.pa.us

src/backend/storage/ipc/procarray.c

index 51f8099cad2ca43d7be1c5b5f66426d282fdbcb1..60b7a5db8e07a6edd8d94b55a041080f98d7e4a8 100644 (file)
@@ -840,13 +840,20 @@ ProcArrayClearTransaction(PGPROC *proc)
    size_t      pgxactoff;
 
    /*
-    * We can skip locking ProcArrayLock exclusively here, because this action
-    * does not actually change anyone's view of the set of running XIDs: our
-    * entry is duplicate with the gxact that has already been inserted into
-    * the ProcArray. But need it in shared mode for pgproc->pgxactoff to stay
-    * the same.
+    * Currently we need to lock ProcArrayLock exclusively here, as we
+    * increment xactCompletionCount below. We also need it at least in shared
+    * mode for pgproc->pgxactoff to stay the same below.
+    *
+    * We could however, as this action does not actually change anyone's view
+    * of the set of running XIDs (our entry is duplicate with the gxact that
+    * has already been inserted into the ProcArray), lower the lock level to
+    * shared if we were to make xactCompletionCount an atomic variable. But
+    * that doesn't seem worth it currently, as a 2PC commit is heavyweight
+    * enough for this not to be the bottleneck.  If it ever becomes a
+    * bottleneck it may also be worth considering to combine this with the
+    * subsequent ProcArrayRemove()
     */
-   LWLockAcquire(ProcArrayLock, LW_SHARED);
+   LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
 
    pgxactoff = proc->pgxactoff;