From c76271cc2ad6b5efd7fdf6c98b16e42e2a495ed1 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 7 Sep 2007 00:58:57 +0000 Subject: [PATCH] Allow CREATE INDEX CONCURRENTLY to disregard transactions in other databases, per gripe from hubert depesz lubaczewski. Patch from Simon Riggs. --- doc/src/sgml/ref/create_index.sgml | 5 +++-- src/backend/commands/indexcmds.c | 8 ++++--- src/backend/storage/ipc/procarray.c | 33 +++++++++++++++++------------ src/include/storage/procarray.h | 3 ++- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/doc/src/sgml/ref/create_index.sgml b/doc/src/sgml/ref/create_index.sgml index 23eec80c1e..c341db255a 100644 --- a/doc/src/sgml/ref/create_index.sgml +++ b/doc/src/sgml/ref/create_index.sgml @@ -308,7 +308,7 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] name @@ -319,7 +319,8 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] nameCONCURRENTLY 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 diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index cf564a50a1..d918d83931 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -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)) { diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 821bdf4ca2..19a2f56a55 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -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; + } } } diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h index 08e2d1f032..12e7a40bf1 100644 --- a/src/include/storage/procarray.h +++ b/src/include/storage/procarray.h @@ -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); -- 2.39.5