mirror of
https://github.com/postgres/postgres.git
synced 2025-10-21 02:52:47 +03:00
Check for conflicting queries during replay of gistvacuumpage()
013ebc0a7b
implements so-called GiST microvacuum. That is gistgettuple() marks index tuples as dead when kill_prior_tuple is set. Later, when new tuple insertion claims page space, those dead index tuples are physically deleted from page. When this deletion is replayed on standby, it might conflict with read-only queries. But013ebc0a7b
doesn't handle this. That may lead to disappearance of some tuples from read-only snapshots on standby. This commit implements resolving of conflicts between replay of GiST microvacuum and standby queries. On the master we implement new WAL record type XLOG_GIST_DELETE, which comprises necessary information. On stable releases we've to be tricky to keep WAL compatibility. Information required for conflict processing is just appended to data of XLOG_GIST_PAGE_UPDATE record. So, PostgreSQL version, which doesn't know about conflict processing, will just ignore that. Reported-by: Andres Freund Diagnosed-by: Andres Freund Discussion: https://postgr.es/m/20181212224524.scafnlyjindmrbe6%40alap3.anarazel.de Author: Alexander Korotkov Backpatch-through: 9.6
This commit is contained in:
@@ -240,6 +240,7 @@ typedef struct GistSplitVector
|
||||
typedef struct
|
||||
{
|
||||
Relation r;
|
||||
Relation heapRel;
|
||||
Size freespace; /* free space to be left */
|
||||
|
||||
GISTInsertStack *stack;
|
||||
@@ -389,7 +390,8 @@ extern void freeGISTstate(GISTSTATE *giststate);
|
||||
extern void gistdoinsert(Relation r,
|
||||
IndexTuple itup,
|
||||
Size freespace,
|
||||
GISTSTATE *GISTstate);
|
||||
GISTSTATE *GISTstate,
|
||||
Relation heapRel);
|
||||
|
||||
/* A List of these is returned from gistplacetopage() in *splitinfo */
|
||||
typedef struct
|
||||
@@ -404,7 +406,8 @@ extern bool gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
|
||||
OffsetNumber oldoffnum, BlockNumber *newblkno,
|
||||
Buffer leftchildbuf,
|
||||
List **splitinfo,
|
||||
bool markleftchild);
|
||||
bool markleftchild,
|
||||
Relation heapRel);
|
||||
|
||||
extern SplitedPageLayout *gistSplit(Relation r, Page page, IndexTuple *itup,
|
||||
int len, GISTSTATE *giststate);
|
||||
@@ -414,6 +417,9 @@ extern XLogRecPtr gistXLogUpdate(Buffer buffer,
|
||||
IndexTuple *itup, int ntup,
|
||||
Buffer leftchild);
|
||||
|
||||
XLogRecPtr gistXLogDelete(Buffer buffer, OffsetNumber *todelete,
|
||||
int ntodelete, RelFileNode hnode);
|
||||
|
||||
extern XLogRecPtr gistXLogSplit(bool page_is_leaf,
|
||||
SplitedPageLayout *dist,
|
||||
BlockNumber origrlink, GistNSN oldnsn,
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include "lib/stringinfo.h"
|
||||
|
||||
#define XLOG_GIST_PAGE_UPDATE 0x00
|
||||
#define XLOG_GIST_DELETE 0x10 /* delete leaf index tuples for a page */
|
||||
/* #define XLOG_GIST_NEW_ROOT 0x20 */ /* not used anymore */
|
||||
#define XLOG_GIST_PAGE_SPLIT 0x30
|
||||
/* #define XLOG_GIST_INSERT_COMPLETE 0x40 */ /* not used anymore */
|
||||
@@ -40,6 +41,22 @@ typedef struct gistxlogPageUpdate
|
||||
*/
|
||||
} gistxlogPageUpdate;
|
||||
|
||||
/*
|
||||
* Backup Blk 0: Leaf page, whose index tuples are deleted.
|
||||
*/
|
||||
typedef struct gistxlogDelete
|
||||
{
|
||||
RelFileNode hnode; /* RelFileNode of the heap the index currently
|
||||
* points at */
|
||||
uint16 ntodelete; /* number of deleted offsets */
|
||||
|
||||
/*
|
||||
* In payload of blk 0 : todelete OffsetNumbers
|
||||
*/
|
||||
} gistxlogDelete;
|
||||
|
||||
#define SizeOfGistxlogDelete (offsetof(gistxlogDelete, ntodelete) + sizeof(uint16))
|
||||
|
||||
/*
|
||||
* Backup Blk 0: If this operation completes a page split, by inserting a
|
||||
* downlink for the split page, the left half of the split
|
||||
|
Reference in New Issue
Block a user