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:44:09 +0000 (09:14 +0530)
committerAmit Kapila <akapila@postgresql.org>
Fri, 19 Nov 2021 03:44:09 +0000 (09:14 +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/access/nbtree/nbtsort.c
src/backend/storage/ipc/procarray.c
src/include/storage/proc.h

index 24fa72983c191b3f4f29d7c98e8101b4a9bb416d..8aab6e324e038a05f2d01f133cf24a208ee9f77f 100644 (file)
@@ -4161,6 +4161,12 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
    LVRelState  vacrel;
    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(MyProc->statusFlags == PROC_IN_VACUUM);
+
    lvshared = (LVShared *) shm_toc_lookup(toc, PARALLEL_VACUUM_KEY_SHARED,
                                           false);
    elevel = lvshared->elevel;
index 5fa6ea8ad9a097a53be8d8c8ae8962b5f7b53a69..78f78e7341b3fef4003a9553f0d7ae716d31b857 100644 (file)
@@ -1814,6 +1814,13 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
        ResetUsage();
 #endif                         /* BTREE_BUILD_STATS */
 
+   /*
+    * The only possible status flag that can be set to the parallel worker is
+    * PROC_IN_SAFE_IC.
+    */
+   Assert((MyProc->statusFlags == 0) ||
+          (MyProc->statusFlags == PROC_IN_SAFE_IC));
+
    /* Set debug_query_string for individual workers first */
    sharedquery = shm_toc_lookup(toc, PARALLEL_KEY_QUERY_TEXT, true);
    debug_query_string = sharedquery;
index 0ccfb3a20a476985910d9f1189995acc6a08284c..9a8429169fc5b0cd148e31a9500149b81e7f1f4e 100644 (file)
@@ -2637,6 +2637,10 @@ ProcArrayInstallImportedXmin(TransactionId xmin,
  * PGPROC of the transaction from which we imported the snapshot, rather than
  * an XID.
  *
+ * Note that this function also copies statusFlags from the source `proc` in
+ * order to avoid the case where MyProc's xmin needs to be skipped for
+ * computing xid horizon.
+ *
  * Returns true if successful, false if source xact is no longer running.
  */
 bool
@@ -2648,8 +2652,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 statusFlags from source proc.
+    */
+   LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
 
    /*
     * Be certain that the referenced PGPROC has an advertised xmin which is
@@ -2662,7 +2668,14 @@ ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
        TransactionIdIsNormal(xid) &&
        TransactionIdPrecedesOrEquals(xid, xmin))
    {
+       /* Install xmin */
        MyProc->xmin = TransactionXmin = xmin;
+
+       /* Flags being copied must be valid copy-able flags. */
+       Assert((proc->statusFlags & (~PROC_COPYABLE_FLAGS)) == 0);
+       MyProc->statusFlags = proc->statusFlags;
+       ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags;
+
        result = true;
    }
 
index be67d8a861660c3ddba8ede8c044d145913b12e8..cfabfdbedf18207e7fac6317c27a874975f2165b 100644 (file)
@@ -65,6 +65,13 @@ struct XidCache
 #define        PROC_VACUUM_STATE_MASK \
    (PROC_IN_VACUUM | PROC_IN_SAFE_IC | PROC_VACUUM_FOR_WRAPAROUND)
 
+/*
+ * Flags that are valid to copy from another proc, the parallel leader
+ * process in practice.  Currently, flags that are set during parallel
+ * vacuum and parallel index creation are allowed.
+ */
+#define        PROC_COPYABLE_FLAGS (PROC_IN_VACUUM | PROC_IN_SAFE_IC)
+
 /*
  * We allow a small number of "weak" relation locks (AccessShareLock,
  * RowShareLock, RowExclusiveLock) to be recorded in the PGPROC structure