diff options
Diffstat (limited to 'src/backend/access/heap/heapam.c')
-rw-r--r-- | src/backend/access/heap/heapam.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index ed0c0c2dc9f..568696333c2 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -2466,7 +2466,11 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, starting_with_empty_page = PageGetMaxOffsetNumber(page) == 0; if (starting_with_empty_page && (options & HEAP_INSERT_FROZEN)) + { all_frozen_set = true; + /* Lock the vmbuffer before entering the critical section */ + LockBuffer(vmbuffer, BUFFER_LOCK_EXCLUSIVE); + } /* NO EREPORT(ERROR) from here till changes are logged */ START_CRIT_SECTION(); @@ -2506,7 +2510,8 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, * going to add further frozen rows to it. * * If we're only adding already frozen rows to a previously empty - * page, mark it as all-visible. + * page, mark it as all-frozen and update the visibility map. We're + * already holding a pin on the vmbuffer. */ if (PageIsAllVisible(page) && !(options & HEAP_INSERT_FROZEN)) { @@ -2517,7 +2522,14 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, vmbuffer, VISIBILITYMAP_VALID_BITS); } else if (all_frozen_set) + { PageSetAllVisible(page); + visibilitymap_set_vmbits(BufferGetBlockNumber(buffer), + vmbuffer, + VISIBILITYMAP_ALL_VISIBLE | + VISIBILITYMAP_ALL_FROZEN, + relation->rd_locator); + } /* * XXX Should we set PageSetPrunable on this page ? See heap_insert() @@ -2565,6 +2577,12 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, xlrec->flags = 0; if (all_visible_cleared) xlrec->flags = XLH_INSERT_ALL_VISIBLE_CLEARED; + + /* + * We don't have to worry about including a conflict xid in the + * WAL record, as HEAP_INSERT_FROZEN intentionally violates + * visibility rules. + */ if (all_frozen_set) xlrec->flags = XLH_INSERT_ALL_FROZEN_SET; @@ -2628,6 +2646,8 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, XLogBeginInsert(); XLogRegisterData(xlrec, tupledata - scratch.data); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD | bufflags); + if (all_frozen_set) + XLogRegisterBuffer(1, vmbuffer, 0); XLogRegisterBufData(0, tupledata, totaldatalen); @@ -2637,26 +2657,17 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, recptr = XLogInsert(RM_HEAP2_ID, info); PageSetLSN(page, recptr); + if (all_frozen_set) + { + Assert(BufferIsDirty(vmbuffer)); + PageSetLSN(BufferGetPage(vmbuffer), recptr); + } } END_CRIT_SECTION(); - /* - * If we've frozen everything on the page, update the visibilitymap. - * We're already holding pin on the vmbuffer. - */ if (all_frozen_set) - { - /* - * It's fine to use InvalidTransactionId here - this is only used - * when HEAP_INSERT_FROZEN is specified, which intentionally - * violates visibility rules. - */ - visibilitymap_set(relation, BufferGetBlockNumber(buffer), buffer, - InvalidXLogRecPtr, vmbuffer, - InvalidTransactionId, - VISIBILITYMAP_ALL_VISIBLE | VISIBILITYMAP_ALL_FROZEN); - } + LockBuffer(vmbuffer, BUFFER_LOCK_UNLOCK); UnlockReleaseBuffer(buffer); ndone += nthispage; |