diff options
| author | Kevin Grittner | 2016-04-08 19:36:30 +0000 |
|---|---|---|
| committer | Kevin Grittner | 2016-04-08 19:36:30 +0000 |
| commit | 848ef42bb8c7909c9d7baa38178d4a209906e7c1 (patch) | |
| tree | e15250d8dfd8f46b15e3ecfddfcad09799cc3866 /src/include | |
| parent | 8b65cf4c5edabdcae45ceaef7b9ac236879aae50 (diff) | |
Add the "snapshot too old" feature
This feature is controlled by a new old_snapshot_threshold GUC. A
value of -1 disables the feature, and that is the default. The
value of 0 is just intended for testing. Above that it is the
number of minutes a snapshot can reach before pruning and vacuum
are allowed to remove dead tuples which the snapshot would
otherwise protect. The xmin associated with a transaction ID does
still protect dead tuples. A connection which is using an "old"
snapshot does not get an error unless it accesses a page modified
recently enough that it might not be able to produce accurate
results.
This is similar to the Oracle feature, and we use the same SQLSTATE
and error message for compatibility.
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/access/brin_revmap.h | 5 | ||||
| -rw-r--r-- | src/include/access/gin_private.h | 4 | ||||
| -rw-r--r-- | src/include/access/nbtree.h | 7 | ||||
| -rw-r--r-- | src/include/storage/bufmgr.h | 19 | ||||
| -rw-r--r-- | src/include/utils/rel.h | 1 | ||||
| -rw-r--r-- | src/include/utils/snapmgr.h | 13 | ||||
| -rw-r--r-- | src/include/utils/snapshot.h | 4 |
7 files changed, 44 insertions, 9 deletions
diff --git a/src/include/access/brin_revmap.h b/src/include/access/brin_revmap.h index 19528bf79ed..89054e01281 100644 --- a/src/include/access/brin_revmap.h +++ b/src/include/access/brin_revmap.h @@ -18,12 +18,13 @@ #include "storage/itemptr.h" #include "storage/off.h" #include "utils/relcache.h" +#include "utils/snapshot.h" /* struct definition lives in brin_revmap.c */ typedef struct BrinRevmap BrinRevmap; extern BrinRevmap *brinRevmapInitialize(Relation idxrel, - BlockNumber *pagesPerRange); + BlockNumber *pagesPerRange, Snapshot snapshot); extern void brinRevmapTerminate(BrinRevmap *revmap); extern void brinRevmapExtend(BrinRevmap *revmap, @@ -34,6 +35,6 @@ extern void brinSetHeapBlockItemptr(Buffer rmbuf, BlockNumber pagesPerRange, BlockNumber heapBlk, ItemPointerData tid); extern BrinTuple *brinGetTupleForHeapBlock(BrinRevmap *revmap, BlockNumber heapBlk, Buffer *buf, OffsetNumber *off, - Size *size, int mode); + Size *size, int mode, Snapshot snapshot); #endif /* BRIN_REVMAP_H */ diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index e212c9ff1e0..a7d4a90d4b1 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -703,7 +703,7 @@ typedef struct * PostingItem */ -extern GinBtreeStack *ginFindLeafPage(GinBtree btree, bool searchMode); +extern GinBtreeStack *ginFindLeafPage(GinBtree btree, bool searchMode, Snapshot snapshot); extern Buffer ginStepRight(Buffer buffer, Relation index, int lockmode); extern void freeGinBtreeStack(GinBtreeStack *stack); extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack, @@ -731,7 +731,7 @@ extern void GinPageDeletePostingItem(Page page, OffsetNumber offset); extern void ginInsertItemPointers(Relation index, BlockNumber rootBlkno, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats); -extern GinBtreeStack *ginScanBeginPostingTree(GinBtree btree, Relation index, BlockNumber rootBlkno); +extern GinBtreeStack *ginScanBeginPostingTree(GinBtree btree, Relation index, BlockNumber rootBlkno, Snapshot snapshot); extern void ginDataFillRoot(GinBtree btree, Page root, BlockNumber lblkno, Page lpage, BlockNumber rblkno, Page rpage); extern void ginPrepareDataScan(GinBtree btree, Relation index, BlockNumber rootBlkno); diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 9046b166bd9..ca5034907dd 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -710,17 +710,18 @@ extern int _bt_pagedel(Relation rel, Buffer buf); */ extern BTStack _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey, - Buffer *bufP, int access); + Buffer *bufP, int access, Snapshot snapshot); extern Buffer _bt_moveright(Relation rel, Buffer buf, int keysz, ScanKey scankey, bool nextkey, bool forupdate, BTStack stack, - int access); + int access, Snapshot snapshot); extern OffsetNumber _bt_binsrch(Relation rel, Buffer buf, int keysz, ScanKey scankey, bool nextkey); extern int32 _bt_compare(Relation rel, int keysz, ScanKey scankey, Page page, OffsetNumber offnum); extern bool _bt_first(IndexScanDesc scan, ScanDirection dir); extern bool _bt_next(IndexScanDesc scan, ScanDirection dir); -extern Buffer _bt_get_endpoint(Relation rel, uint32 level, bool rightmost); +extern Buffer _bt_get_endpoint(Relation rel, uint32 level, bool rightmost, + Snapshot snapshot); /* * prototypes for functions in nbtutils.c diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index 4c15934f36b..6fea1bc13dc 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -180,11 +180,26 @@ extern PGDLLIMPORT int32 *LocalRefCount; /* * BufferGetPage * Returns the page associated with a buffer. + * + * agetest will normally be a literal, so use a macro at the outer level to + * give the compiler a chance to optimize away the runtime code to check it. + * + * TestForOldSnapshot(), if it doesn't throw an error, will return the page + * argument it is passed, so the same result will go back to this macro's + * caller for either agetest value; it is a matter of whether to call the + * function to perform the test. For call sites where the check is not needed + * (which is the vast majority of them), the snapshot and relation parameters + * can, and generally should, be NULL. */ #define BufferGetPage(buffer, snapshot, relation, agetest) \ ( \ - AssertMacro((agetest) == BGP_NO_SNAPSHOT_TEST), \ - ((Page)BufferGetBlock(buffer)) \ + ( \ + AssertMacro((agetest) == BGP_NO_SNAPSHOT_TEST || (agetest) == BGP_TEST_FOR_OLD_SNAPSHOT), \ + ((agetest) == BGP_NO_SNAPSHOT_TEST) \ + ) ? \ + ((Page)BufferGetBlock(buffer)) \ + : \ + (TestForOldSnapshot(snapshot, relation, (Page)BufferGetBlock(buffer))) \ ) /* diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index c7582c2a11c..b5d82d60042 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -15,6 +15,7 @@ #define REL_H #include "access/tupdesc.h" +#include "access/xlog.h" #include "catalog/pg_class.h" #include "catalog/pg_index.h" #include "fmgr.h" diff --git a/src/include/utils/snapmgr.h b/src/include/utils/snapmgr.h index a9e9066dd29..371042a6077 100644 --- a/src/include/utils/snapmgr.h +++ b/src/include/utils/snapmgr.h @@ -14,10 +14,20 @@ #define SNAPMGR_H #include "fmgr.h" +#include "utils/relcache.h" #include "utils/resowner.h" #include "utils/snapshot.h" +/* GUC variables */ +extern int old_snapshot_threshold; + + +extern Size SnapMgrShmemSize(void); +extern void SnapMgrInit(void); +extern int64 GetSnapshotCurrentTimestamp(void); +extern int64 GetOldSnapshotThresholdTimestamp(void); + extern bool FirstSnapshotSet; extern TransactionId TransactionXmin; @@ -54,6 +64,9 @@ extern void ImportSnapshot(const char *idstr); extern bool XactHasExportedSnapshots(void); extern void DeleteAllExportedSnapshotFiles(void); extern bool ThereAreNoPriorRegisteredSnapshots(void); +extern TransactionId TransactionIdLimitedForOldSnapshots(TransactionId recentXmin, + Relation relation); +extern void MaintainOldSnapshotTimeMapping(int64 whenTaken, TransactionId xmin); extern char *ExportSnapshot(Snapshot snapshot); diff --git a/src/include/utils/snapshot.h b/src/include/utils/snapshot.h index 2a563633d2b..998e2e593d0 100644 --- a/src/include/utils/snapshot.h +++ b/src/include/utils/snapshot.h @@ -14,6 +14,7 @@ #define SNAPSHOT_H #include "access/htup.h" +#include "access/xlogdefs.h" #include "lib/pairingheap.h" #include "storage/buf.h" @@ -105,6 +106,9 @@ typedef struct SnapshotData uint32 active_count; /* refcount on ActiveSnapshot stack */ uint32 regd_count; /* refcount on RegisteredSnapshots */ pairingheap_node ph_node; /* link in the RegisteredSnapshots heap */ + + int64 whenTaken; /* timestamp when snapshot was taken */ + XLogRecPtr lsn; /* position in the WAL stream when taken */ } SnapshotData; /* |
