mirror of
https://github.com/postgres/postgres.git
synced 2025-10-25 13:17:41 +03:00
Change the way we mark tuples as frozen.
Instead of changing the tuple xmin to FrozenTransactionId, the combination of HEAP_XMIN_COMMITTED and HEAP_XMIN_INVALID, which were previously never set together, is now defined as HEAP_XMIN_FROZEN. A variety of previous proposals to freeze tuples opportunistically before vacuum_freeze_min_age is reached have foundered on the objection that replacing xmin by FrozenTransactionId might hinder debugging efforts when things in this area go awry; this patch is intended to solve that problem by keeping the XID around (but largely ignoring the value to which it is set). Third-party code that checks for HEAP_XMIN_INVALID on tuples where HEAP_XMIN_COMMITTED might be set will be broken by this change. To fix, use the new accessor macros in htup_details.h rather than consulting the bits directly. HeapTupleHeaderGetXmin has been modified to return FrozenTransactionId when the infomask bits indicate that the tuple is frozen; use HeapTupleHeaderGetRawXmin when you already know that the tuple isn't marked commited or frozen, or want the raw value anyway. We currently do this in routines that display the xmin for user consumption, in tqual.c where it's known to be safe and important for the avoidance of extra cycles, and in the function-caching code for various procedural languages, which shouldn't invalidate the cache just because the tuple gets frozen. Robert Haas and Andres Freund
This commit is contained in:
@@ -274,7 +274,7 @@ typedef struct xl_heap_inplace
|
||||
* This struct represents a 'freeze plan', which is what we need to know about
|
||||
* a single tuple being frozen during vacuum.
|
||||
*/
|
||||
#define XLH_FREEZE_XMIN 0x01
|
||||
/* 0x01 was XLH_FREEZE_XMIN */
|
||||
#define XLH_FREEZE_XVAC 0x02
|
||||
#define XLH_INVALID_XVAC 0x04
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "access/htup.h"
|
||||
#include "access/tupdesc.h"
|
||||
#include "access/tupmacs.h"
|
||||
#include "access/transam.h"
|
||||
#include "storage/bufpage.h"
|
||||
|
||||
/*
|
||||
@@ -175,6 +176,7 @@ struct HeapTupleHeaderData
|
||||
HEAP_XMAX_KEYSHR_LOCK)
|
||||
#define HEAP_XMIN_COMMITTED 0x0100 /* t_xmin committed */
|
||||
#define HEAP_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */
|
||||
#define HEAP_XMIN_FROZEN (HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)
|
||||
#define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */
|
||||
#define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */
|
||||
#define HEAP_XMAX_IS_MULTI 0x1000 /* t_xmax is a MultiXactId */
|
||||
@@ -244,16 +246,64 @@ struct HeapTupleHeaderData
|
||||
* macros evaluate their other argument only once.
|
||||
*/
|
||||
|
||||
#define HeapTupleHeaderGetXmin(tup) \
|
||||
/*
|
||||
* HeapTupleHeaderGetRawXmin returns the "raw" xmin field, which is the xid
|
||||
* originally used to insert the tuple. However, the tuple might actually
|
||||
* be frozen (via HeapTupleHeaderSetXminFrozen) in which case the tuple's xmin
|
||||
* is visible to every snapshot. Prior to PostgreSQL 9.4, we actually changed
|
||||
* the xmin to FrozenTransactionId, and that value may still be encountered
|
||||
* on disk.
|
||||
*/
|
||||
#define HeapTupleHeaderGetRawXmin(tup) \
|
||||
( \
|
||||
(tup)->t_choice.t_heap.t_xmin \
|
||||
)
|
||||
|
||||
#define HeapTupleHeaderGetXmin(tup) \
|
||||
( \
|
||||
HeapTupleHeaderXminFrozen(tup) ? \
|
||||
FrozenTransactionId : HeapTupleHeaderGetRawXmin(tup) \
|
||||
)
|
||||
|
||||
#define HeapTupleHeaderSetXmin(tup, xid) \
|
||||
( \
|
||||
(tup)->t_choice.t_heap.t_xmin = (xid) \
|
||||
)
|
||||
|
||||
#define HeapTupleHeaderXminCommitted(tup) \
|
||||
( \
|
||||
(tup)->t_infomask & HEAP_XMIN_COMMITTED \
|
||||
)
|
||||
|
||||
#define HeapTupleHeaderXminInvalid(tup) \
|
||||
( \
|
||||
((tup)->t_infomask & (HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)) == \
|
||||
HEAP_XMIN_INVALID \
|
||||
)
|
||||
|
||||
#define HeapTupleHeaderXminFrozen(tup) \
|
||||
( \
|
||||
((tup)->t_infomask & (HEAP_XMIN_FROZEN)) == HEAP_XMIN_FROZEN \
|
||||
)
|
||||
|
||||
#define HeapTupleHeaderSetXminCommitted(tup) \
|
||||
( \
|
||||
AssertMacro(!HeapTupleHeaderXminInvalid(tup)), \
|
||||
((tup)->t_infomask |= HEAP_XMIN_COMMITTED) \
|
||||
)
|
||||
|
||||
#define HeapTupleHeaderSetXminInvalid(tup) \
|
||||
( \
|
||||
AssertMacro(!HeapTupleHeaderXminCommitted(tup)), \
|
||||
((tup)->t_infomask |= HEAP_XMIN_INVALID) \
|
||||
)
|
||||
|
||||
#define HeapTupleHeaderSetXminFrozen(tup) \
|
||||
( \
|
||||
AssertMacro(!HeapTupleHeaderXminInvalid(tup)), \
|
||||
((tup)->t_infomask |= HEAP_XMIN_FROZEN) \
|
||||
)
|
||||
|
||||
/*
|
||||
* HeapTupleHeaderGetRawXmax gets you the raw Xmax field. To find out the Xid
|
||||
* that updated a tuple, you might need to resolve the MultiXactId if certain
|
||||
@@ -374,7 +424,8 @@ do { \
|
||||
#define HeapTupleHeaderIsHotUpdated(tup) \
|
||||
( \
|
||||
((tup)->t_infomask2 & HEAP_HOT_UPDATED) != 0 && \
|
||||
((tup)->t_infomask & (HEAP_XMIN_INVALID | HEAP_XMAX_INVALID)) == 0 \
|
||||
((tup)->t_infomask & HEAP_XMAX_INVALID) == 0 && \
|
||||
!HeapTupleHeaderXminInvalid(tup) \
|
||||
)
|
||||
|
||||
#define HeapTupleHeaderSetHotUpdated(tup) \
|
||||
|
||||
@@ -55,7 +55,7 @@ typedef struct BkpBlock
|
||||
/*
|
||||
* Each page of XLOG file has a header like this:
|
||||
*/
|
||||
#define XLOG_PAGE_MAGIC 0xD07A /* can be used as WAL version indicator */
|
||||
#define XLOG_PAGE_MAGIC 0xD07B /* can be used as WAL version indicator */
|
||||
|
||||
typedef struct XLogPageHeaderData
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user