diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/access/brin/brin.c | 41 | ||||
-rw-r--r-- | src/backend/catalog/index.c | 36 |
2 files changed, 44 insertions, 33 deletions
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 360b26e6fc4..fc9f964bf78 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -696,7 +696,7 @@ brinbuildempty(PG_FUNCTION_ARGS) * * XXX we could mark item tuples as "dirty" (when a minimum or maximum heap * tuple is deleted), meaning the need to re-run summarization on the affected - * range. Need to an extra flag in brintuples for that. + * range. Would need to add an extra flag in brintuples for that. */ Datum brinbulkdelete(PG_FUNCTION_ARGS) @@ -951,9 +951,13 @@ summarize_range(IndexInfo *indexInfo, BrinBuildState *state, Relation heapRel, * Execute the partial heap scan covering the heap blocks in the specified * page range, summarizing the heap tuples in it. This scan stops just * short of brinbuildCallback creating the new index entry. + * + * Note that it is critical we use the "any visible" mode of + * IndexBuildHeapRangeScan here: otherwise, we would miss tuples inserted + * by transactions that are still in progress, among other corner cases. */ state->bs_currRangeStart = heapBlk; - IndexBuildHeapRangeScan(heapRel, state->bs_irel, indexInfo, false, + IndexBuildHeapRangeScan(heapRel, state->bs_irel, indexInfo, false, true, heapBlk, state->bs_pagesPerRange, brinbuildCallback, (void *) state); @@ -1058,36 +1062,6 @@ brinsummarize(Relation index, Relation heapRel, double *numSummarized, state = initialize_brin_buildstate(index, revmap, pagesPerRange); indexInfo = BuildIndexInfo(index); - - /* - * We only have ShareUpdateExclusiveLock on the table, and - * therefore other sessions may insert tuples into the range - * we're going to scan. This is okay, because we take - * additional precautions to avoid losing the additional - * tuples; see comments in summarize_range. Set the - * concurrent flag, which causes IndexBuildHeapRangeScan to - * use a snapshot other than SnapshotAny, and silences - * warnings emitted there. - */ - indexInfo->ii_Concurrent = true; - - /* - * If using transaction-snapshot mode, it would be possible - * for another transaction to insert a tuple that's not - * visible to our snapshot if we have already acquired one, - * when in snapshot-isolation mode; therefore, disallow this - * from running in such a transaction unless a snapshot hasn't - * been acquired yet. - * - * This code is called by VACUUM and - * brin_summarize_new_values. Have the error message mention - * the latter because VACUUM cannot run in a transaction and - * thus cannot cause this issue. - */ - if (IsolationUsesXactSnapshot() && FirstSnapshotSet) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TRANSACTION_STATE), - errmsg("brin_summarize_new_values() cannot run in a transaction that has already obtained a snapshot"))); } summarize_range(indexInfo, state, heapRel, heapBlk); @@ -1111,7 +1085,10 @@ brinsummarize(Relation index, Relation heapRel, double *numSummarized, /* free resources */ brinRevmapTerminate(revmap); if (state) + { terminate_brin_buildstate(state); + pfree(indexInfo); + } } /* diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 69f35c93309..e59b163173c 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2161,6 +2161,7 @@ IndexBuildHeapScan(Relation heapRelation, { return IndexBuildHeapRangeScan(heapRelation, indexRelation, indexInfo, allow_sync, + false, 0, InvalidBlockNumber, callback, callback_state); } @@ -2170,12 +2171,17 @@ IndexBuildHeapScan(Relation heapRelation, * number of blocks are scanned. Scan to end-of-rel can be signalled by * passing InvalidBlockNumber as numblocks. Note that restricting the range * to scan cannot be done when requesting syncscan. + * + * When "anyvisible" mode is requested, all tuples visible to any transaction + * are considered, including those inserted or deleted by transactions that are + * still in progress. */ double IndexBuildHeapRangeScan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, + bool anyvisible, BlockNumber start_blockno, BlockNumber numblocks, IndexBuildCallback callback, @@ -2210,6 +2216,12 @@ IndexBuildHeapRangeScan(Relation heapRelation, indexInfo->ii_ExclusionOps != NULL); /* + * "Any visible" mode is not compatible with uniqueness checks; make sure + * only one of those is requested. + */ + Assert(!(anyvisible && checking_uniqueness)); + + /* * Need an EState for evaluation of index expressions and partial-index * predicates. Also a slot to hold the current tuple. */ @@ -2236,6 +2248,9 @@ IndexBuildHeapRangeScan(Relation heapRelation, { snapshot = RegisterSnapshot(GetTransactionSnapshot()); OldestXmin = InvalidTransactionId; /* not used */ + + /* "any visible" mode is not compatible with this */ + Assert(!anyvisible); } else { @@ -2364,6 +2379,17 @@ IndexBuildHeapRangeScan(Relation heapRelation, case HEAPTUPLE_INSERT_IN_PROGRESS: /* + * In "anyvisible" mode, this tuple is visible and we don't + * need any further checks. + */ + if (anyvisible) + { + indexIt = true; + tupleIsAlive = true; + break; + } + + /* * Since caller should hold ShareLock or better, normally * the only way to see this is if it was inserted earlier * in our own transaction. However, it can happen in @@ -2409,8 +2435,16 @@ IndexBuildHeapRangeScan(Relation heapRelation, /* * As with INSERT_IN_PROGRESS case, this is unexpected - * unless it's our own deletion or a system catalog. + * unless it's our own deletion or a system catalog; + * but in anyvisible mode, this tuple is visible. */ + if (anyvisible) + { + indexIt = true; + tupleIsAlive = false; + break; + } + xwait = HeapTupleHeaderGetUpdateXid(heapTuple->t_data); if (!TransactionIdIsCurrentTransactionId(xwait)) { |