From ceb9360067221fb8ad26bdfa0c3c08b2f355044e Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 9 Jan 2008 21:52:36 +0000
Subject: [PATCH] Fix CREATE INDEX CONCURRENTLY to not deadlock against an
 automatic or manual VACUUM that is blocked waiting to get lock on the table
 being indexed. Per report and fix suggestion from Greg Stark.

---
 src/backend/commands/indexcmds.c    | 19 ++++++++++++++-----
 src/backend/storage/ipc/procarray.c | 11 ++++++++---
 src/include/storage/procarray.h     |  4 ++--
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index efa25a1ad91..952109f7845 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.169 2008/01/01 19:45:49 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.170 2008/01/09 21:52:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,6 +38,7 @@
 #include "parser/parse_expr.h"
 #include "parser/parse_func.h"
 #include "parser/parsetree.h"
+#include "storage/proc.h"
 #include "storage/procarray.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
@@ -630,11 +631,19 @@ DefineIndex(RangeVar *heapRelation,
 	 * We can exclude any running transactions that have xmin >= the xmax of
 	 * our reference snapshot, since they are clearly not interested in any
 	 * missing older tuples.  Transactions in other DBs aren't a problem
-	 * either, since they'll never even be able to see this index. Also,
-	 * GetCurrentVirtualXIDs never reports our own vxid, so we need not check
-	 * for that.
+	 * either, since they'll never even be able to see this index.
+	 *
+	 * We can also exclude autovacuum processes and processes running manual
+	 * lazy VACUUMs, because they won't be fazed by missing index entries
+	 * either.  (Manual ANALYZEs, however, can't be excluded because they
+	 * might be within transactions that are going to do arbitrary operations
+	 * later.)
+	 *
+	 * Also, GetCurrentVirtualXIDs never reports our own vxid, so we need not
+	 * check for that.
 	 */
-	old_snapshots = GetCurrentVirtualXIDs(ActiveSnapshot->xmax, false);
+	old_snapshots = GetCurrentVirtualXIDs(ActiveSnapshot->xmax, false,
+										  PROC_IS_AUTOVACUUM | PROC_IN_VACUUM);
 
 	while (VirtualTransactionIdIsValid(*old_snapshots))
 	{
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 89441f64f1e..575b138c435 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -23,7 +23,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.39 2008/01/01 19:45:51 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.40 2008/01/09 21:52:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1006,10 +1006,12 @@ IsBackendPid(int pid)
  *
  * If limitXmin is not InvalidTransactionId, we skip any backends
  * with xmin >= limitXmin.	If allDbs is false, we skip backends attached
- * to other databases.	Also, our own process is always skipped.
+ * to other databases.  If excludeVacuum isn't zero, we skip processes for
+ * which (excludeVacuum & vacuumFlags) is not zero.  Also, our own process
+ * is always skipped.
  */
 VirtualTransactionId *
-GetCurrentVirtualXIDs(TransactionId limitXmin, bool allDbs)
+GetCurrentVirtualXIDs(TransactionId limitXmin, bool allDbs, int excludeVacuum)
 {
 	VirtualTransactionId *vxids;
 	ProcArrayStruct *arrayP = procArray;
@@ -1029,6 +1031,9 @@ GetCurrentVirtualXIDs(TransactionId limitXmin, bool allDbs)
 		if (proc == MyProc)
 			continue;
 
+		if (excludeVacuum & proc->vacuumFlags)
+			continue;
+
 		if (allDbs || proc->databaseId == MyDatabaseId)
 		{
 			/* Fetch xmin just once - might change on us? */
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index 5e0b1fd6ba5..26b27fa9418 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.19 2008/01/01 19:45:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.20 2008/01/09 21:52:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,7 +37,7 @@ extern int	BackendXidGetPid(TransactionId xid);
 extern bool IsBackendPid(int pid);
 
 extern VirtualTransactionId *GetCurrentVirtualXIDs(TransactionId limitXmin,
-					  bool allDbs);
+					  bool allDbs, int excludeVacuum);
 extern int	CountActiveBackends(void);
 extern int	CountDBBackends(Oid databaseid);
 extern int	CountUserBackends(Oid roleid);
-- 
GitLab