Commit cd1aae58 authored by Tom Lane's avatar Tom Lane

Allow CREATE INDEX CONCURRENTLY to disregard transactions in other

databases, per gripe from hubert depesz lubaczewski.  Patch from
Simon Riggs.
parent f8942f4a
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_index.sgml,v 1.63 2007/06/03 17:05:53 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/create_index.sgml,v 1.64 2007/09/07 00:58:56 tgl Exp $
PostgreSQL documentation
-->
......@@ -308,7 +308,7 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] <replaceable class="parameter">name</re
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.
</para>
......@@ -319,7 +319,8 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] <replaceable class="parameter">name</re
<literal>CONCURRENTLY</> option of <command>CREATE INDEX</>.
When this option is used,
<productname>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
......
......@@ -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))
{
......
......@@ -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;
}
}
}
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment