diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 2815d916f3ddd4b7844dc0fdc164b5161714b499..38bba1629979e113001c61497eb5bf124b21df68 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -2423,7 +2423,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, PageClearAllVisible(BufferGetPage(buffer)); visibilitymap_clear(relation, ItemPointerGetBlockNumber(&(heaptup->t_self)), - vmbuffer); + vmbuffer, VISIBILITYMAP_VALID_BITS); } /* @@ -2737,7 +2737,7 @@ heap_multi_insert(Relation relation, HeapTuple *tuples, int ntuples, PageClearAllVisible(page); visibilitymap_clear(relation, BufferGetBlockNumber(buffer), - vmbuffer); + vmbuffer, VISIBILITYMAP_VALID_BITS); } /* @@ -3239,7 +3239,7 @@ l1: all_visible_cleared = true; PageClearAllVisible(page); visibilitymap_clear(relation, BufferGetBlockNumber(buffer), - vmbuffer); + vmbuffer, VISIBILITYMAP_VALID_BITS); } /* store transaction information of xact deleting the tuple */ @@ -3925,6 +3925,7 @@ l2: TransactionId xmax_lock_old_tuple; uint16 infomask_lock_old_tuple, infomask2_lock_old_tuple; + bool cleared_all_frozen = false; /* * To prevent concurrent sessions from updating the tuple, we have to @@ -3968,6 +3969,17 @@ l2: /* temporarily make it look not-updated, but locked */ oldtup.t_data->t_ctid = oldtup.t_self; + /* + * Clear all-frozen bit on visibility map if needed. We could + * immediately reset ALL_VISIBLE, but given that the WAL logging + * overhead would be unchanged, that doesn't seem necessarily + * worthwhile. + */ + if (PageIsAllVisible(BufferGetPage(buffer)) && + visibilitymap_clear(relation, block, vmbuffer, + VISIBILITYMAP_ALL_FROZEN)) + cleared_all_frozen = true; + MarkBufferDirty(buffer); if (RelationNeedsWAL(relation)) @@ -3982,6 +3994,8 @@ l2: xlrec.locking_xid = xmax_lock_old_tuple; xlrec.infobits_set = compute_infobits(oldtup.t_data->t_infomask, oldtup.t_data->t_infomask2); + xlrec.flags = + cleared_all_frozen ? XLH_LOCK_ALL_FROZEN_CLEARED : 0; XLogRegisterData((char *) &xlrec, SizeOfHeapLock); recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_LOCK); PageSetLSN(page, recptr); @@ -4159,20 +4173,20 @@ l2: /* record address of new tuple in t_ctid of old one */ oldtup.t_data->t_ctid = heaptup->t_self; - /* clear PD_ALL_VISIBLE flags */ + /* clear PD_ALL_VISIBLE flags, reset all visibilitymap bits */ if (PageIsAllVisible(BufferGetPage(buffer))) { all_visible_cleared = true; PageClearAllVisible(BufferGetPage(buffer)); visibilitymap_clear(relation, BufferGetBlockNumber(buffer), - vmbuffer); + vmbuffer, VISIBILITYMAP_VALID_BITS); } if (newbuf != buffer && PageIsAllVisible(BufferGetPage(newbuf))) { all_visible_cleared_new = true; PageClearAllVisible(BufferGetPage(newbuf)); visibilitymap_clear(relation, BufferGetBlockNumber(newbuf), - vmbuffer_new); + vmbuffer_new, VISIBILITYMAP_VALID_BITS); } if (newbuf != buffer) @@ -4556,6 +4570,8 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, ItemPointer tid = &(tuple->t_self); ItemId lp; Page page; + Buffer vmbuffer = InvalidBuffer; + BlockNumber block; TransactionId xid, xmax; uint16 old_infomask, @@ -4563,8 +4579,19 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, new_infomask2; bool first_time = true; bool have_tuple_lock = false; + bool cleared_all_frozen = false; *buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid)); + block = ItemPointerGetBlockNumber(tid); + + /* + * Before locking the buffer, pin the visibility map page if it may be + * necessary. XXX: It might be possible for this to change after acquiring + * the lock below. We don't yet deal with that case. + */ + if (PageIsAllVisible(BufferGetPage(*buffer))) + visibilitymap_pin(relation, block, &vmbuffer); + LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE); page = BufferGetPage(*buffer); @@ -4580,15 +4607,14 @@ l3: if (result == HeapTupleInvisible) { - LockBuffer(*buffer, BUFFER_LOCK_UNLOCK); - /* * This is possible, but only when locking a tuple for ON CONFLICT * UPDATE. We return this value here rather than throwing an error in * order to give that case the opportunity to throw a more specific * error. */ - return HeapTupleInvisible; + result = HeapTupleInvisible; + goto out_locked; } else if (result == HeapTupleBeingUpdated || result == HeapTupleUpdated) { @@ -4646,7 +4672,8 @@ l3: if (TUPLOCK_from_mxstatus(members[i].status) >= mode) { pfree(members); - return HeapTupleMayBeUpdated; + result = HeapTupleMayBeUpdated; + goto out_unlocked; } } @@ -4661,21 +4688,30 @@ l3: Assert(HEAP_XMAX_IS_KEYSHR_LOCKED(infomask) || HEAP_XMAX_IS_SHR_LOCKED(infomask) || HEAP_XMAX_IS_EXCL_LOCKED(infomask)); - return HeapTupleMayBeUpdated; - break; + result = HeapTupleMayBeUpdated; + goto out_unlocked; case LockTupleShare: if (HEAP_XMAX_IS_SHR_LOCKED(infomask) || HEAP_XMAX_IS_EXCL_LOCKED(infomask)) - return HeapTupleMayBeUpdated; + { + result = HeapTupleMayBeUpdated; + goto out_unlocked; + } break; case LockTupleNoKeyExclusive: if (HEAP_XMAX_IS_EXCL_LOCKED(infomask)) - return HeapTupleMayBeUpdated; + { + result = HeapTupleMayBeUpdated; + goto out_unlocked; + } break; case LockTupleExclusive: if (HEAP_XMAX_IS_EXCL_LOCKED(infomask) && infomask2 & HEAP_KEYS_UPDATED) - return HeapTupleMayBeUpdated; + { + result = HeapTupleMayBeUpdated; + goto out_unlocked; + } break; } } @@ -5036,10 +5072,7 @@ failed: hufd->cmax = HeapTupleHeaderGetCmax(tuple->t_data); else hufd->cmax = InvalidCommandId; - LockBuffer(*buffer, BUFFER_LOCK_UNLOCK); - if (have_tuple_lock) - UnlockTupleTuplock(relation, tid, mode); - return result; + goto out_locked; } xmax = HeapTupleHeaderGetRawXmax(tuple->t_data); @@ -5094,6 +5127,13 @@ failed: if (HEAP_XMAX_IS_LOCKED_ONLY(new_infomask)) tuple->t_data->t_ctid = *tid; + /* Clear only the all-frozen bit on visibility map if needed */ + if (PageIsAllVisible(page) && + visibilitymap_clear(relation, block, vmbuffer, + VISIBILITYMAP_ALL_FROZEN)) + cleared_all_frozen = true; + + MarkBufferDirty(*buffer); /* @@ -5120,6 +5160,7 @@ failed: xlrec.locking_xid = xid; xlrec.infobits_set = compute_infobits(new_infomask, tuple->t_data->t_infomask2); + xlrec.flags = cleared_all_frozen ? XLH_LOCK_ALL_FROZEN_CLEARED : 0; XLogRegisterData((char *) &xlrec, SizeOfHeapLock); /* we don't decode row locks atm, so no need to log the origin */ @@ -5131,8 +5172,15 @@ failed: END_CRIT_SECTION(); + result = HeapTupleMayBeUpdated; + +out_locked: LockBuffer(*buffer, BUFFER_LOCK_UNLOCK); +out_unlocked: + if (BufferIsValid(vmbuffer)) + ReleaseBuffer(vmbuffer); + /* * Don't update the visibility map here. Locking a tuple doesn't change * visibility info. @@ -5145,7 +5193,7 @@ failed: if (have_tuple_lock) UnlockTupleTuplock(relation, tid, mode); - return HeapTupleMayBeUpdated; + return result; } /* @@ -5577,6 +5625,7 @@ static HTSU_Result heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid, LockTupleMode mode) { + HTSU_Result result; ItemPointerData tupid; HeapTupleData mytup; Buffer buf; @@ -5587,6 +5636,9 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid, TransactionId xmax, new_xmax; TransactionId priorXmax = InvalidTransactionId; + bool cleared_all_frozen = false; + Buffer vmbuffer = InvalidBuffer; + BlockNumber block; ItemPointerCopy(tid, &tupid); @@ -5594,6 +5646,7 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid, { new_infomask = 0; new_xmax = InvalidTransactionId; + block = ItemPointerGetBlockNumber(&tupid); ItemPointerCopy(&tupid, &(mytup.t_self)); if (!heap_fetch(rel, SnapshotAny, &mytup, &buf, false, NULL)) @@ -5610,6 +5663,17 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid, l4: CHECK_FOR_INTERRUPTS(); + + /* + * Before locking the buffer, pin the visibility map page if it may be + * necessary. XXX: It might be possible for this to change after + * acquiring the lock below. We don't yet deal with that case. + */ + if (PageIsAllVisible(BufferGetPage(buf))) + visibilitymap_pin(rel, block, &vmbuffer); + else + vmbuffer = InvalidBuffer; + LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); /* @@ -5620,8 +5684,8 @@ l4: !TransactionIdEquals(HeapTupleHeaderGetXmin(mytup.t_data), priorXmax)) { - UnlockReleaseBuffer(buf); - return HeapTupleMayBeUpdated; + result = HeapTupleMayBeUpdated; + goto out_locked; } old_infomask = mytup.t_data->t_infomask; @@ -5661,11 +5725,9 @@ l4: HEAP_XMAX_IS_LOCKED_ONLY(old_infomask)); for (i = 0; i < nmembers; i++) { - HTSU_Result res; - - res = test_lockmode_for_conflict(members[i].status, - members[i].xid, - mode, &needwait); + result = test_lockmode_for_conflict(members[i].status, + members[i].xid, + mode, &needwait); if (needwait) { @@ -5676,11 +5738,10 @@ l4: pfree(members); goto l4; } - if (res != HeapTupleMayBeUpdated) + if (result != HeapTupleMayBeUpdated) { - UnlockReleaseBuffer(buf); pfree(members); - return res; + goto out_locked; } } if (members) @@ -5688,7 +5749,6 @@ l4: } else { - HTSU_Result res; MultiXactStatus status; /* @@ -5727,8 +5787,8 @@ l4: status = MultiXactStatusNoKeyUpdate; } - res = test_lockmode_for_conflict(status, rawxmax, mode, - &needwait); + result = test_lockmode_for_conflict(status, rawxmax, mode, + &needwait); if (needwait) { LockBuffer(buf, BUFFER_LOCK_UNLOCK); @@ -5736,10 +5796,9 @@ l4: XLTW_LockUpdated); goto l4; } - if (res != HeapTupleMayBeUpdated) + if (result != HeapTupleMayBeUpdated) { - UnlockReleaseBuffer(buf); - return res; + goto out_locked; } } } @@ -5749,6 +5808,11 @@ l4: xid, mode, false, &new_xmax, &new_infomask, &new_infomask2); + if (PageIsAllVisible(BufferGetPage(buf)) && + visibilitymap_clear(rel, block, vmbuffer, + VISIBILITYMAP_ALL_FROZEN)) + cleared_all_frozen = true; + START_CRIT_SECTION(); /* ... and set them */ @@ -5773,6 +5837,8 @@ l4: xlrec.offnum = ItemPointerGetOffsetNumber(&mytup.t_self); xlrec.xmax = new_xmax; xlrec.infobits_set = compute_infobits(new_infomask, new_infomask2); + xlrec.flags = + cleared_all_frozen ? XLH_LOCK_ALL_FROZEN_CLEARED : 0; XLogRegisterData((char *) &xlrec, SizeOfHeapLockUpdated); @@ -5788,15 +5854,28 @@ l4: ItemPointerEquals(&mytup.t_self, &mytup.t_data->t_ctid) || HeapTupleHeaderIsOnlyLocked(mytup.t_data)) { - UnlockReleaseBuffer(buf); - return HeapTupleMayBeUpdated; + result = HeapTupleMayBeUpdated; + goto out_locked; } /* tail recursion */ priorXmax = HeapTupleHeaderGetUpdateXid(mytup.t_data); ItemPointerCopy(&(mytup.t_data->t_ctid), &tupid); UnlockReleaseBuffer(buf); + if (vmbuffer != InvalidBuffer) + ReleaseBuffer(vmbuffer); } + + result = HeapTupleMayBeUpdated; + +out_locked: + UnlockReleaseBuffer(buf); + + if (vmbuffer != InvalidBuffer) + ReleaseBuffer(vmbuffer); + + return result; + } /* @@ -8107,7 +8186,7 @@ heap_xlog_delete(XLogReaderState *record) Buffer vmbuffer = InvalidBuffer; visibilitymap_pin(reln, blkno, &vmbuffer); - visibilitymap_clear(reln, blkno, vmbuffer); + visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); ReleaseBuffer(vmbuffer); FreeFakeRelcacheEntry(reln); } @@ -8185,7 +8264,7 @@ heap_xlog_insert(XLogReaderState *record) Buffer vmbuffer = InvalidBuffer; visibilitymap_pin(reln, blkno, &vmbuffer); - visibilitymap_clear(reln, blkno, vmbuffer); + visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); ReleaseBuffer(vmbuffer); FreeFakeRelcacheEntry(reln); } @@ -8305,7 +8384,7 @@ heap_xlog_multi_insert(XLogReaderState *record) Buffer vmbuffer = InvalidBuffer; visibilitymap_pin(reln, blkno, &vmbuffer); - visibilitymap_clear(reln, blkno, vmbuffer); + visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); ReleaseBuffer(vmbuffer); FreeFakeRelcacheEntry(reln); } @@ -8460,7 +8539,7 @@ heap_xlog_update(XLogReaderState *record, bool hot_update) Buffer vmbuffer = InvalidBuffer; visibilitymap_pin(reln, oldblk, &vmbuffer); - visibilitymap_clear(reln, oldblk, vmbuffer); + visibilitymap_clear(reln, oldblk, vmbuffer, VISIBILITYMAP_VALID_BITS); ReleaseBuffer(vmbuffer); FreeFakeRelcacheEntry(reln); } @@ -8544,7 +8623,7 @@ heap_xlog_update(XLogReaderState *record, bool hot_update) Buffer vmbuffer = InvalidBuffer; visibilitymap_pin(reln, newblk, &vmbuffer); - visibilitymap_clear(reln, newblk, vmbuffer); + visibilitymap_clear(reln, newblk, vmbuffer, VISIBILITYMAP_VALID_BITS); ReleaseBuffer(vmbuffer); FreeFakeRelcacheEntry(reln); } @@ -8724,6 +8803,27 @@ heap_xlog_lock(XLogReaderState *record) ItemId lp = NULL; HeapTupleHeader htup; + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_LOCK_ALL_FROZEN_CLEARED) + { + RelFileNode rnode; + Buffer vmbuffer = InvalidBuffer; + BlockNumber block; + Relation reln; + + XLogRecGetBlockTag(record, 0, &rnode, NULL, &block); + reln = CreateFakeRelcacheEntry(rnode); + + visibilitymap_pin(reln, block, &vmbuffer); + visibilitymap_clear(reln, block, vmbuffer, VISIBILITYMAP_ALL_FROZEN); + + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) { page = (Page) BufferGetPage(buffer); @@ -8776,6 +8876,27 @@ heap_xlog_lock_updated(XLogReaderState *record) xlrec = (xl_heap_lock_updated *) XLogRecGetData(record); + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_LOCK_ALL_FROZEN_CLEARED) + { + RelFileNode rnode; + Buffer vmbuffer = InvalidBuffer; + BlockNumber block; + Relation reln; + + XLogRecGetBlockTag(record, 0, &rnode, NULL, &block); + reln = CreateFakeRelcacheEntry(rnode); + + visibilitymap_pin(reln, block, &vmbuffer); + visibilitymap_clear(reln, block, vmbuffer, VISIBILITYMAP_ALL_FROZEN); + + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) { page = BufferGetPage(buffer); diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c index b472d31a03c2bbe3d003458d78608ebd56db97dc..3ad4a9f5870ddf68120eb1566ec00fa400d1b2be 100644 --- a/src/backend/access/heap/visibilitymap.c +++ b/src/backend/access/heap/visibilitymap.c @@ -11,7 +11,7 @@ * src/backend/access/heap/visibilitymap.c * * INTERFACE ROUTINES - * visibilitymap_clear - clear a bit in the visibility map + * visibilitymap_clear - clear bits for one page in the visibility map * visibilitymap_pin - pin a map page for setting a bit * visibilitymap_pin_ok - check whether correct map page is already pinned * visibilitymap_set - set a bit in a previously pinned page @@ -159,20 +159,23 @@ static void vm_extend(Relation rel, BlockNumber nvmblocks); /* - * visibilitymap_clear - clear all bits for one page in visibility map + * visibilitymap_clear - clear specified bits for one page in visibility map * * You must pass a buffer containing the correct map page to this function. * Call visibilitymap_pin first to pin the right one. This function doesn't do - * any I/O. + * any I/O. Returns true if any bits have been cleared and false otherwise. */ -void -visibilitymap_clear(Relation rel, BlockNumber heapBlk, Buffer buf) +bool +visibilitymap_clear(Relation rel, BlockNumber heapBlk, Buffer buf, uint8 flags) { BlockNumber mapBlock = HEAPBLK_TO_MAPBLOCK(heapBlk); int mapByte = HEAPBLK_TO_MAPBYTE(heapBlk); int mapOffset = HEAPBLK_TO_OFFSET(heapBlk); - uint8 mask = VISIBILITYMAP_VALID_BITS << mapOffset; + uint8 mask = flags << mapOffset; char *map; + bool cleared = false; + + Assert(flags & VISIBILITYMAP_VALID_BITS); #ifdef TRACE_VISIBILITYMAP elog(DEBUG1, "vm_clear %s %d", RelationGetRelationName(rel), heapBlk); @@ -189,9 +192,12 @@ visibilitymap_clear(Relation rel, BlockNumber heapBlk, Buffer buf) map[mapByte] &= ~mask; MarkBufferDirty(buf); + cleared = true; } LockBuffer(buf, BUFFER_LOCK_UNLOCK); + + return cleared; } /* diff --git a/src/backend/access/rmgrdesc/heapdesc.c b/src/backend/access/rmgrdesc/heapdesc.c index 2b31ea413c31d97566fbb8093287754ab79851e5..7c763b6b0ef773f72a5000a7b0923f57b716850f 100644 --- a/src/backend/access/rmgrdesc/heapdesc.c +++ b/src/backend/access/rmgrdesc/heapdesc.c @@ -85,7 +85,8 @@ heap_desc(StringInfo buf, XLogReaderState *record) { xl_heap_lock *xlrec = (xl_heap_lock *) rec; - appendStringInfo(buf, "off %u: xid %u ", xlrec->offnum, xlrec->locking_xid); + appendStringInfo(buf, "off %u: xid %u: flags %u ", + xlrec->offnum, xlrec->locking_xid, xlrec->flags); out_infobits(buf, xlrec->infobits_set); } else if (info == XLOG_HEAP_INPLACE) @@ -138,7 +139,8 @@ heap2_desc(StringInfo buf, XLogReaderState *record) { xl_heap_lock_updated *xlrec = (xl_heap_lock_updated *) rec; - appendStringInfo(buf, "off %u: xmax %u ", xlrec->offnum, xlrec->xmax); + appendStringInfo(buf, "off %u: xmax %u: flags %u ", + xlrec->offnum, xlrec->xmax, xlrec->flags); out_infobits(buf, xlrec->infobits_set); } else if (info == XLOG_HEAP2_NEW_CID) diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 32b6fddc6220c63a6287f1e789241e28aaf6cf11..4075f4d1c92246da90632d9399c41b5723fa1157 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -1179,7 +1179,8 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, { elog(WARNING, "page is not marked all-visible but visibility map bit is set in relation \"%s\" page %u", relname, blkno); - visibilitymap_clear(onerel, blkno, vmbuffer); + visibilitymap_clear(onerel, blkno, vmbuffer, + VISIBILITYMAP_VALID_BITS); } /* @@ -1201,7 +1202,8 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, relname, blkno); PageClearAllVisible(page); MarkBufferDirty(buf); - visibilitymap_clear(onerel, blkno, vmbuffer); + visibilitymap_clear(onerel, blkno, vmbuffer, + VISIBILITYMAP_VALID_BITS); } /* diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h index a822d0b82dc3cb729167653d1ac3852cb2a5c07c..06a82426bb524787b717523a70ede427a7410ae8 100644 --- a/src/include/access/heapam_xlog.h +++ b/src/include/access/heapam_xlog.h @@ -243,15 +243,19 @@ typedef struct xl_heap_cleanup_info #define XLHL_XMAX_KEYSHR_LOCK 0x08 #define XLHL_KEYS_UPDATED 0x10 +/* flag bits for xl_heap_lock / xl_heap_lock_updated's flag field */ +#define XLH_LOCK_ALL_FROZEN_CLEARED 0x01 + /* This is what we need to know about lock */ typedef struct xl_heap_lock { TransactionId locking_xid; /* might be a MultiXactId not xid */ OffsetNumber offnum; /* locked tuple's offset on page */ int8 infobits_set; /* infomask and infomask2 bits to set */ + uint8 flags; /* XLH_LOCK_* flag bits */ } xl_heap_lock; -#define SizeOfHeapLock (offsetof(xl_heap_lock, infobits_set) + sizeof(int8)) +#define SizeOfHeapLock (offsetof(xl_heap_lock, flags) + sizeof(int8)) /* This is what we need to know about locking an updated version of a row */ typedef struct xl_heap_lock_updated @@ -259,9 +263,10 @@ typedef struct xl_heap_lock_updated TransactionId xmax; OffsetNumber offnum; uint8 infobits_set; + uint8 flags; } xl_heap_lock_updated; -#define SizeOfHeapLockUpdated (offsetof(xl_heap_lock_updated, infobits_set) + sizeof(uint8)) +#define SizeOfHeapLockUpdated (offsetof(xl_heap_lock_updated, flags) + sizeof(uint8)) /* This is what we need to know about confirmation of speculative insertion */ typedef struct xl_heap_confirm diff --git a/src/include/access/visibilitymap.h b/src/include/access/visibilitymap.h index fca99ca318d1e8979ba9c429150748b0f953c7be..00bbd4c2d946de5d066c2a4aecbda87cab5ea733 100644 --- a/src/include/access/visibilitymap.h +++ b/src/include/access/visibilitymap.h @@ -34,8 +34,8 @@ #define VM_ALL_FROZEN(r, b, v) \ ((visibilitymap_get_status((r), (b), (v)) & VISIBILITYMAP_ALL_FROZEN) != 0) -extern void visibilitymap_clear(Relation rel, BlockNumber heapBlk, - Buffer vmbuf); +extern bool visibilitymap_clear(Relation rel, BlockNumber heapBlk, + Buffer vmbuf, uint8 flags); extern void visibilitymap_pin(Relation rel, BlockNumber heapBlk, Buffer *vmbuf); extern bool visibilitymap_pin_ok(BlockNumber heapBlk, Buffer vmbuf); diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h index 2627519ba0866defaa496f2e7ba23f5865d842df..0a595ccc4816aa21e4400244a024b3c801c96989 100644 --- a/src/include/access/xlog_internal.h +++ b/src/include/access/xlog_internal.h @@ -31,7 +31,7 @@ /* * Each page of XLOG file has a header like this: */ -#define XLOG_PAGE_MAGIC 0xD092 /* can be used as WAL version indicator */ +#define XLOG_PAGE_MAGIC 0xD093 /* can be used as WAL version indicator */ typedef struct XLogPageHeaderData {