]> granicus.if.org Git - postgresql/commitdiff
Only allow autovacuum to be auto-canceled by a directly blocked process.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 26 Jul 2012 18:29:22 +0000 (14:29 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 26 Jul 2012 18:29:22 +0000 (14:29 -0400)
In the original coding of the autovacuum cancel feature, commit
acac68b2bcae818bc8803b8cb8cbb17eee8d5e2b, an autovacuum process was
considered a target for cancellation if it was found to hard-block any
process examined in the deadlock search.  This patch tightens the test so
that the autovacuum must directly hard-block the current process.  This
should make the behavior more predictable in general, and in particular
it ensures that an autovacuum will not be canceled with less than
deadlock_timeout grace period.  In the old coding, it was possible for an
autovacuum to be canceled almost instantly, given unfortunate timing of two
or more other processes' lock attempts.

This also justifies the logging methodology in the recent commit
d7318d43d891bd63e82dcfc27948113ed7b1db80; without this restriction, that
patch isn't providing enough information to see the connection of the
canceling process to the autovacuum.  Like that one, patch all the way
back.

src/backend/storage/lmgr/deadlock.c

index 288186a6ceebf40d5a43638c7be5be35c12dd3b3..697ef6e495abf185392da5f2958137f70ebf8237 100644 (file)
@@ -527,25 +527,6 @@ FindLockCycleRecurse(PGPROC *checkProc,
                                if ((proclock->holdMask & LOCKBIT_ON(lm)) &&
                                        (conflictMask & LOCKBIT_ON(lm)))
                                {
-                                       /*
-                                        * Look for a blocking autovacuum. There can be more than
-                                        * one in the deadlock cycle, in which case we just pick a
-                                        * random one.  We stash the autovacuum worker's PGPROC so
-                                        * that the caller can send a cancel signal to it, if
-                                        * appropriate.
-                                        *
-                                        * Note we read vacuumFlags without any locking.  This is
-                                        * OK only for checking the PROC_IS_AUTOVACUUM flag,
-                                        * because that flag is set at process start and never
-                                        * reset; there is logic elsewhere to avoid canceling an
-                                        * autovacuum that is working for preventing Xid
-                                        * wraparound problems (which needs to read a different
-                                        * vacuumFlag bit), but we don't do that here to avoid
-                                        * grabbing ProcArrayLock.
-                                        */
-                                       if (pgxact->vacuumFlags & PROC_IS_AUTOVACUUM)
-                                               blocking_autovacuum_proc = proc;
-
                                        /* This proc hard-blocks checkProc */
                                        if (FindLockCycleRecurse(proc, depth + 1,
                                                                                         softEdges, nSoftEdges))
@@ -559,7 +540,34 @@ FindLockCycleRecurse(PGPROC *checkProc,
 
                                                return true;
                                        }
-                                       /* If no deadlock, we're done looking at this proclock */
+
+                                       /*
+                                        * No deadlock here, but see if this proc is an autovacuum
+                                        * that is directly hard-blocking our own proc.  If so,
+                                        * report it so that the caller can send a cancel signal
+                                        * to it, if appropriate.  If there's more than one such
+                                        * proc, it's indeterminate which one will be reported.
+                                        *
+                                        * We don't touch autovacuums that are indirectly blocking
+                                        * us; it's up to the direct blockee to take action.  This
+                                        * rule simplifies understanding the behavior and ensures
+                                        * that an autovacuum won't be canceled with less than
+                                        * deadlock_timeout grace period.
+                                        *
+                                        * Note we read vacuumFlags without any locking.  This is
+                                        * OK only for checking the PROC_IS_AUTOVACUUM flag,
+                                        * because that flag is set at process start and never
+                                        * reset.  There is logic elsewhere to avoid canceling an
+                                        * autovacuum that is working to prevent XID wraparound
+                                        * problems (which needs to read a different vacuumFlag
+                                        * bit), but we don't do that here to avoid grabbing
+                                        * ProcArrayLock.
+                                        */
+                                       if (checkProc == MyProc &&
+                                               pgxact->vacuumFlags & PROC_IS_AUTOVACUUM)
+                                               blocking_autovacuum_proc = proc;
+
+                                       /* We're done looking at this proclock */
                                        break;
                                }
                        }