Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Fix parallel operations that prevent oldest xmin from advancing.
authorAmit Kapila <akapila@postgresql.org>
Fri, 19 Nov 2021 03:54:00 +0000 (09:24 +0530)
committerAmit Kapila <akapila@postgresql.org>
Fri, 19 Nov 2021 03:54:00 +0000 (09:24 +0530)
While determining xid horizons, we skip over backends that are running
Vacuum. We also ignore Create Index Concurrently, or Reindex Concurrently
for the purposes of computing Xmin for Vacuum. But we were not setting the
flags corresponding to these operations when they are performed in
parallel which was preventing Xid horizon from advancing.

The optimization related to skipping Create Index Concurrently, or Reindex
Concurrently operations was implemented in PG-14 but the fix is the same
for the Parallel Vacuum as well so back-patched till PG-13.

Author: Masahiko Sawada
Reviewed-by: Amit Kapila
Backpatch-through: 13
Discussion: https://postgr.es/m/CAD21AoCLQqgM1sXh9BrDFq0uzd3RBFKi=Vfo6cjjKODm0Onr5w@mail.gmail.com

src/backend/access/heap/vacuumlazy.c
src/backend/storage/ipc/procarray.c
src/include/storage/proc.h

index fe2a6062b9c45c59f7be45264b248360a8bff3ce..e1bb97951b0b726d0bf912193e432c8fbba24c9a 100644 (file)
@@ -3482,6 +3482,12 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
    LVRelStats  vacrelstats;
    ErrorContextCallback errcallback;
 
+   /*
+    * A parallel vacuum worker must have only PROC_IN_VACUUM flag since we
+    * don't support parallel vacuum for autovacuum as of now.
+    */
+   Assert(MyPgXact->vacuumFlags == PROC_IN_VACUUM);
+
    lvshared = (LVShared *) shm_toc_lookup(toc, PARALLEL_VACUUM_KEY_SHARED,
                                           false);
    elevel = lvshared->elevel;
index 828ed2a38a119837516b542a959612f6a96a01ca..2f1d4af17a59442531eead7f6cc2dc3c934b639b 100644 (file)
@@ -1864,6 +1864,10 @@ ProcArrayInstallImportedXmin(TransactionId xmin,
  * PGPROC of the transaction from which we imported the snapshot, rather than
  * an XID.
  *
+ * Note that this function also copies vacuumFlags from the source `proc` in
+ * order to avoid the case where MyPgXact's xmin needs to be skipped for
+ * computing xid horizon.
+ *
  * Returns true if successful, false if source xact is no longer running.
  */
 bool
@@ -1876,8 +1880,10 @@ ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
    Assert(TransactionIdIsNormal(xmin));
    Assert(proc != NULL);
 
-   /* Get lock so source xact can't end while we're doing this */
-   LWLockAcquire(ProcArrayLock, LW_SHARED);
+   /*
+    * Get an exclusive lock so that we can copy vacuumFlags from source proc.
+    */
+   LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
 
    pgxact = &allPgXact[proc->pgprocno];
 
@@ -1892,7 +1898,13 @@ ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
        TransactionIdIsNormal(xid) &&
        TransactionIdPrecedesOrEquals(xid, xmin))
    {
+       /* Install xmin */
        MyPgXact->xmin = TransactionXmin = xmin;
+
+       /* Flags being copied must be valid copy-able flags. */
+       Assert((pgxact->vacuumFlags & (~PROC_COPYABLE_FLAGS)) == 0);
+       MyPgXact->vacuumFlags = pgxact->vacuumFlags;
+
        result = true;
    }
 
index 1ee9000b2b9c443bc022be30966e2f30c6d4404d..b3ea1a258601b3f01692d24825b624d517ecf16d 100644 (file)
@@ -62,6 +62,13 @@ struct XidCache
 #define        PROC_VACUUM_STATE_MASK \
    (PROC_IN_VACUUM | PROC_IN_ANALYZE | PROC_VACUUM_FOR_WRAPAROUND)
 
+/*
+ * Flags that are valid to copy from another proc, the parallel leader
+ * process in practice.  Currently, a flag that is set during parallel
+ * vacuum is allowed.
+ */
+#define        PROC_COPYABLE_FLAGS (PROC_IN_VACUUM)
+
 /*
  * We allow a small number of "weak" relation locks (AccessShareLock,
  * RowShareLock, RowExclusiveLock) to be recorded in the PGPROC structure