@ -93,6 +93,7 @@ static void ReindexPartitions(Oid relid, int options, bool isTopLevel);
static void ReindexMultipleInternal ( List * relids , int options ) ;
static void ReindexMultipleInternal ( List * relids , int options ) ;
static bool ReindexRelationConcurrently ( Oid relationOid , int options ) ;
static bool ReindexRelationConcurrently ( Oid relationOid , int options ) ;
static void update_relispartition ( Oid relationId , bool newval ) ;
static void update_relispartition ( Oid relationId , bool newval ) ;
static inline void set_indexsafe_procflags ( void ) ;
/*
/*
* callback argument type for RangeVarCallbackForReindexIndex ( )
* callback argument type for RangeVarCallbackForReindexIndex ( )
@ -384,7 +385,10 @@ CompareOpclassOptions(Datum *opts1, Datum *opts2, int natts)
* lazy VACUUMs , because they won ' t be fazed by missing index entries
* lazy VACUUMs , because they won ' t be fazed by missing index entries
* either . ( Manual ANALYZEs , however , can ' t be excluded because they
* either . ( Manual ANALYZEs , however , can ' t be excluded because they
* might be within transactions that are going to do arbitrary operations
* might be within transactions that are going to do arbitrary operations
* later . )
* later . ) Processes running CREATE INDEX CONCURRENTLY
* on indexes that are neither expressional nor partial are also safe to
* ignore , since we know that those processes won ' t examine any data
* outside the table they ' re indexing .
*
*
* Also , GetCurrentVirtualXIDs never reports our own vxid , so we need not
* Also , GetCurrentVirtualXIDs never reports our own vxid , so we need not
* check for that .
* check for that .
@ -405,7 +409,8 @@ WaitForOlderSnapshots(TransactionId limitXmin, bool progress)
VirtualTransactionId * old_snapshots ;
VirtualTransactionId * old_snapshots ;
old_snapshots = GetCurrentVirtualXIDs ( limitXmin , true , false ,
old_snapshots = GetCurrentVirtualXIDs ( limitXmin , true , false ,
PROC_IS_AUTOVACUUM | PROC_IN_VACUUM ,
PROC_IS_AUTOVACUUM | PROC_IN_VACUUM
| PROC_IN_SAFE_IC ,
& n_old_snapshots ) ;
& n_old_snapshots ) ;
if ( progress )
if ( progress )
pgstat_progress_update_param ( PROGRESS_WAITFOR_TOTAL , n_old_snapshots ) ;
pgstat_progress_update_param ( PROGRESS_WAITFOR_TOTAL , n_old_snapshots ) ;
@ -425,7 +430,8 @@ WaitForOlderSnapshots(TransactionId limitXmin, bool progress)
newer_snapshots = GetCurrentVirtualXIDs ( limitXmin ,
newer_snapshots = GetCurrentVirtualXIDs ( limitXmin ,
true , false ,
true , false ,
PROC_IS_AUTOVACUUM | PROC_IN_VACUUM ,
PROC_IS_AUTOVACUUM | PROC_IN_VACUUM
| PROC_IN_SAFE_IC ,
& n_newer_snapshots ) ;
& n_newer_snapshots ) ;
for ( j = i ; j < n_old_snapshots ; j + + )
for ( j = i ; j < n_old_snapshots ; j + + )
{
{
@ -518,6 +524,7 @@ DefineIndex(Oid relationId,
bool amcanorder ;
bool amcanorder ;
amoptions_function amoptions ;
amoptions_function amoptions ;
bool partitioned ;
bool partitioned ;
bool safe_index ;
Datum reloptions ;
Datum reloptions ;
int16 * coloptions ;
int16 * coloptions ;
IndexInfo * indexInfo ;
IndexInfo * indexInfo ;
@ -1044,6 +1051,10 @@ DefineIndex(Oid relationId,
}
}
}
}
/* Is index safe for others to ignore? See set_indexsafe_procflags() */
safe_index = indexInfo - > ii_Expressions = = NIL & &
indexInfo - > ii_Predicate = = NIL ;
/*
/*
* Report index creation if appropriate ( delay this till after most of the
* Report index creation if appropriate ( delay this till after most of the
* error checks )
* error checks )
@ -1430,6 +1441,10 @@ DefineIndex(Oid relationId,
CommitTransactionCommand ( ) ;
CommitTransactionCommand ( ) ;
StartTransactionCommand ( ) ;
StartTransactionCommand ( ) ;
/* Tell concurrent index builds to ignore us, if index qualifies */
if ( safe_index )
set_indexsafe_procflags ( ) ;
/*
/*
* The index is now visible , so we can report the OID .
* The index is now visible , so we can report the OID .
*/
*/
@ -1489,6 +1504,10 @@ DefineIndex(Oid relationId,
CommitTransactionCommand ( ) ;
CommitTransactionCommand ( ) ;
StartTransactionCommand ( ) ;
StartTransactionCommand ( ) ;
/* Tell concurrent index builds to ignore us, if index qualifies */
if ( safe_index )
set_indexsafe_procflags ( ) ;
/*
/*
* Phase 3 of concurrent index build
* Phase 3 of concurrent index build
*
*
@ -1545,6 +1564,10 @@ DefineIndex(Oid relationId,
CommitTransactionCommand ( ) ;
CommitTransactionCommand ( ) ;
StartTransactionCommand ( ) ;
StartTransactionCommand ( ) ;
/* Tell concurrent index builds to ignore us, if index qualifies */
if ( safe_index )
set_indexsafe_procflags ( ) ;
/* We should now definitely not be advertising any xmin. */
/* We should now definitely not be advertising any xmin. */
Assert ( MyProc - > xmin = = InvalidTransactionId ) ;
Assert ( MyProc - > xmin = = InvalidTransactionId ) ;
@ -3896,3 +3919,37 @@ update_relispartition(Oid relationId, bool newval)
heap_freetuple ( tup ) ;
heap_freetuple ( tup ) ;
table_close ( classRel , RowExclusiveLock ) ;
table_close ( classRel , RowExclusiveLock ) ;
}
}
/*
* Set the PROC_IN_SAFE_IC flag in MyProc - > statusFlags .
*
* When doing concurrent index builds , we can set this flag
* to tell other processes concurrently running CREATE
* INDEX CONCURRENTLY or REINDEX CONCURRENTLY to ignore us when
* doing their waits for concurrent snapshots . On one hand it
* avoids pointlessly waiting for a process that ' s not interesting
* anyway ; but more importantly it avoids deadlocks in some cases .
*
* This can be done safely only for indexes that don ' t execute any
* expressions that could access other tables , so index must not be
* expressional nor partial . Caller is responsible for only calling
* this routine when that assumption holds true .
*
* ( The flag is reset automatically at transaction end , so it must be
* set for each transaction . )
*/
static inline void
set_indexsafe_procflags ( void )
{
/*
* This should only be called before installing xid or xmin in MyProc ;
* otherwise , concurrent processes could see an Xmin that moves backwards .
*/
Assert ( MyProc - > xid = = InvalidTransactionId & &
MyProc - > xmin = = InvalidTransactionId ) ;
LWLockAcquire ( ProcArrayLock , LW_EXCLUSIVE ) ;
MyProc - > statusFlags | = PROC_IN_SAFE_IC ;
ProcGlobal - > statusFlags [ MyProc - > pgxactoff ] = MyProc - > statusFlags ;
LWLockRelease ( ProcArrayLock ) ;
}