From b4dc21e928cd38f6e641144f08c60ccd0b2d0d4e Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Thu, 17 Jan 2019 12:25:26 +0900 Subject: [PATCH 2/3] Refactor index concurrent build into its own routine This is used by CREATE INDEX CONCURRENTLY, and finds its uses for other concurrent-safe operations as the index building step happens in an independent transaction, like REINDEX CONCURRENTLY. This simplifies at the same time index_build() which has been including a flag to track primary indexes, but this was not used. This is removed, simplifying this refactoring on the way. --- src/backend/bootstrap/bootstrap.c | 2 +- src/backend/catalog/heap.c | 2 +- src/backend/catalog/index.c | 58 ++++++++++++++++++++++++++++--- src/backend/commands/indexcmds.c | 28 ++------------- src/include/catalog/index.h | 3 +- 5 files changed, 60 insertions(+), 33 deletions(-) diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 63bb134949..a3242cae50 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -1131,7 +1131,7 @@ build_indices(void) heap = heap_open(ILHead->il_heap, NoLock); ind = index_open(ILHead->il_ind, NoLock); - index_build(heap, ind, ILHead->il_info, false, false, false); + index_build(heap, ind, ILHead->il_info, false, false); index_close(ind, NoLock); heap_close(heap, NoLock); diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index d7ccf2bfbe..f1364d29de 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -3063,7 +3063,7 @@ RelationTruncateIndexes(Relation heapRelation) /* Initialize the index and rebuild */ /* Note: we do not need to re-establish pkey setting */ - index_build(heapRelation, currentIndex, indexInfo, false, true, false); + index_build(heapRelation, currentIndex, indexInfo, true, false); /* We're done with this index */ index_close(currentIndex, NoLock); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 8701e3a791..2447952f59 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -1190,8 +1190,7 @@ index_create(Relation heapRelation, } else { - index_build(heapRelation, indexRelation, indexInfo, isprimary, false, - true); + index_build(heapRelation, indexRelation, indexInfo, false, true); } /* @@ -2236,7 +2235,6 @@ void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, - bool isprimary, bool isreindex, bool parallel) { @@ -2398,6 +2396,58 @@ index_build(Relation heapRelation, } +/* + * index_build_concurrent - build index for a concurrent operation. + * + * Low-level locks are taken when this operation is performed to prevent + * only schema changes, but they need to be kept until the end of the + * transaction performing this operation. 'indexOid' refers to an index + * relation OID already created as part of previous processing, and + * 'heapOid' refers to its parent heap relation. + */ +void +index_build_concurrent(Oid heapOid, Oid indexOid) +{ + Relation heapRel, + indexRelation; + IndexInfo *indexInfo; + + /* This had better make sure that a snapshot is active */ + Assert(ActiveSnapshotSet()); + + /* Open and lock the parent heap relation */ + heapRel = heap_open(heapOid, ShareUpdateExclusiveLock); + + /* And the target index relation */ + indexRelation = index_open(indexOid, RowExclusiveLock); + + /* + * We have to re-build the IndexInfo struct, since it was lost in the + * commit of the transaction where this concurrent index was created at + * the catalog level. + */ + indexInfo = BuildIndexInfo(indexRelation); + Assert(!indexInfo->ii_ReadyForInserts); + indexInfo->ii_Concurrent = true; + indexInfo->ii_BrokenHotChain = false; + + /* Now build the index */ + index_build(heapRel, indexRelation, indexInfo, false, true); + + /* Close both relations, and keep the locks */ + heap_close(heapRel, NoLock); + index_close(indexRelation, NoLock); + + /* + * Update the pg_index row to mark the index as ready for inserts. Once + * we commit this transaction, any new transactions that open the table + * must insert new entries into the index for insertions and non-HOT + * updates. + */ + index_set_state_flags(indexOid, INDEX_CREATE_SET_READY); +} + + /* * IndexBuildHeapScan - scan the heap relation to find tuples to be indexed * @@ -3703,7 +3753,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, /* Initialize the index and rebuild */ /* Note: we do not need to re-establish pkey setting */ - index_build(heapRelation, iRel, indexInfo, false, true, true); + index_build(heapRelation, iRel, indexInfo, true, true); } PG_CATCH(); { diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index a81e656059..930d4d9880 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -347,7 +347,6 @@ DefineIndex(Oid relationId, List *indexColNames; List *allIndexParams; Relation rel; - Relation indexRelation; HeapTuple tuple; Form_pg_am accessMethodForm; IndexAmRoutine *amRoutine; @@ -1151,34 +1150,11 @@ DefineIndex(Oid relationId, * HOT-chain or the extension of the chain is HOT-safe for this index. */ - /* Open and lock the parent heap relation */ - rel = heap_open(relationId, ShareUpdateExclusiveLock); - - /* And the target index relation */ - indexRelation = index_open(indexRelationId, RowExclusiveLock); - /* Set ActiveSnapshot since functions in the indexes may need it */ PushActiveSnapshot(GetTransactionSnapshot()); - /* We have to re-build the IndexInfo struct, since it was lost in commit */ - indexInfo = BuildIndexInfo(indexRelation); - Assert(!indexInfo->ii_ReadyForInserts); - indexInfo->ii_Concurrent = true; - indexInfo->ii_BrokenHotChain = false; - - /* Now build the index */ - index_build(rel, indexRelation, indexInfo, stmt->primary, false, true); - - /* Close both the relations, but keep the locks */ - heap_close(rel, NoLock); - index_close(indexRelation, NoLock); - - /* - * Update the pg_index row to mark the index as ready for inserts. Once we - * commit this transaction, any new transactions that open the table must - * insert new entries into the index for insertions and non-HOT updates. - */ - index_set_state_flags(indexRelationId, INDEX_CREATE_SET_READY); + /* Perform concurrent build of index */ + index_build_concurrent(relationId, indexRelationId); /* we can do away with our snapshot */ PopActiveSnapshot(); diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 8daac5663c..129c00fd0c 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -107,10 +107,11 @@ extern void FormIndexDatum(IndexInfo *indexInfo, extern void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, - bool isprimary, bool isreindex, bool parallel); +extern void index_build_concurrent(Oid heapOid, Oid indexOid); + extern double IndexBuildHeapScan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, -- 2.20.1