Allow CREATE INDEX CONCURRENTLY to disregard transactions in other
authorTom Lane
Fri, 7 Sep 2007 00:58:57 +0000 (00:58 +0000)
committerTom Lane
Fri, 7 Sep 2007 00:58:57 +0000 (00:58 +0000)
databases, per gripe from hubert depesz lubaczewski.  Patch from
Simon Riggs.

doc/src/sgml/ref/create_index.sgml
src/backend/commands/indexcmds.c
src/backend/storage/ipc/procarray.c
src/include/storage/procarray.h

index ed2b8e22e70c2c9dc87120e4a6e7259708d096c9..0fe40c775f8554447fe0fc0521f627e29dbac087 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -308,7 +308,7 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] name
     table. Other transactions can still read the table, but if they try to
     insert, update, or delete rows in the table they will block until the
     index build is finished. This could have a severe effect if the system is
-    a live production database. Large tables can take many hours to be
+    a live production database.  Very large tables can take many hours to be
     indexed, and even for smaller tables, an index build can lock out writers
     for periods that are unacceptably long for a production system.
    
@@ -319,7 +319,8 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] name
     CONCURRENTLY option of CREATE INDEX.
     When this option is used,
     PostgreSQL must perform two scans of the table, and in
-    addition it must wait for all existing transactions to terminate.  Thus
+    addition it must wait for all existing transactions that could potentially
+    use the index to terminate.  Thus
     this method requires more total work than a standard index build and takes
     significantly longer to complete.  However, since it allows normal
     operations to continue while the index is built, this method is useful for
index ac56b583f17d8726986fba0975bd696e16e308b8..5c418f8b7a3af0abd36723640c8029edccc4e4e2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.163 2007/09/05 18:10:47 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.164 2007/09/07 00:58:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -535,10 +535,12 @@ 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.  Also, GetCurrentVirtualXIDs never reports our
-    * own vxid, so we need not check for that.
+    * 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.
     */
-   old_snapshots = GetCurrentVirtualXIDs(ActiveSnapshot->xmax);
+   old_snapshots = GetCurrentVirtualXIDs(ActiveSnapshot->xmax, false);
 
    while (VirtualTransactionIdIsValid(*old_snapshots))
    {
index a467df990e1e6bde2e6eea9daf3aac5183f5aae6..15701b959cef14baa319567eb624df62e2412794 100644 (file)
@@ -23,7 +23,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.30 2007/09/05 21:11:19 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.31 2007/09/07 00:58:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -891,10 +891,11 @@ IsBackendPid(int pid)
  * The array is palloc'd and is terminated with an invalid VXID.
  *
  * If limitXmin is not InvalidTransactionId, we skip any backends
- * with xmin >= limitXmin.  Also, our own process is always skipped.
+ * with xmin >= limitXmin.  If allDbs is false, we skip backends attached
+ * to other databases.  Also, our own process is always skipped.
  */
 VirtualTransactionId *
-GetCurrentVirtualXIDs(TransactionId limitXmin)
+GetCurrentVirtualXIDs(TransactionId limitXmin, bool allDbs)
 {
    VirtualTransactionId *vxids;
    ProcArrayStruct *arrayP = procArray;
@@ -910,24 +911,28 @@ GetCurrentVirtualXIDs(TransactionId limitXmin)
    for (index = 0; index < arrayP->numProcs; index++)
    {
        volatile PGPROC    *proc = arrayP->procs[index];
-       /* Fetch xmin just once - might change on us? */
-       TransactionId pxmin = proc->xmin;
 
        if (proc == MyProc)
            continue;
 
-       /*
-        * Note that InvalidTransactionId precedes all other XIDs, so a
-        * proc that hasn't set xmin yet will always be included.
-        */
-       if (!TransactionIdIsValid(limitXmin) ||
-           TransactionIdPrecedes(pxmin, limitXmin))
+       if (allDbs || proc->databaseId == MyDatabaseId)
        {
-           VirtualTransactionId vxid;
+           /* Fetch xmin just once - might change on us? */
+           TransactionId pxmin = proc->xmin;
+
+           /*
+            * Note that InvalidTransactionId precedes all other XIDs, so a
+            * proc that hasn't set xmin yet will always be included.
+            */
+           if (!TransactionIdIsValid(limitXmin) ||
+               TransactionIdPrecedes(pxmin, limitXmin))
+           {
+               VirtualTransactionId vxid;
 
-           GET_VXID_FROM_PGPROC(vxid, *proc);
-           if (VirtualTransactionIdIsValid(vxid))
-               vxids[count++] = vxid;
+               GET_VXID_FROM_PGPROC(vxid, *proc);
+               if (VirtualTransactionIdIsValid(vxid))
+                   vxids[count++] = vxid;
+           }
        }
    }
 
index 524710506a7dfc78ad1d21f8990b54a1b3249ccd..21e0c8395224937529b25256bec2944bfad27011 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.15 2007/09/05 18:10:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.16 2007/09/07 00:58:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,7 +33,8 @@ extern PGPROC *BackendPidGetProc(int pid);
 extern int BackendXidGetPid(TransactionId xid);
 extern bool IsBackendPid(int pid);
 
-extern VirtualTransactionId *GetCurrentVirtualXIDs(TransactionId limitXmin);
+extern VirtualTransactionId *GetCurrentVirtualXIDs(TransactionId limitXmin,
+                                                  bool allDbs);
 extern int CountActiveBackends(void);
 extern int CountDBBackends(Oid databaseid);
 extern int CountUserBackends(Oid roleid);