1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-01 01:04:50 +03:00

Fix full-page writes of internal GIN pages.

Insertion to a non-leaf GIN page didn't make a full-page image of the page,
which is wrong. The code used to do it correctly, but was changed (commit
853d1c3103fa961ae6219f0281885b345593d101) because the redo-routine didn't
track incomplete splits correctly when the page was restored from a full
page image. Of course, that was not right way to fix it, the redo routine
should've been fixed instead. The redo-routine was surreptitiously fixed
in 2010 (commit 4016bdef8aded77b4903c457050622a5a1815c16), so all we need
to do now is revert the code that creates the record to its original form.

This doesn't change the format of the WAL record.

Backpatch to all supported versions.
This commit is contained in:
Heikki Linnakangas 2013-12-03 22:13:16 +02:00
parent 6698782f19
commit 06df57ac62
2 changed files with 33 additions and 49 deletions

View File

@ -381,7 +381,6 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
{ {
Page page = BufferGetPage(buf); Page page = BufferGetPage(buf);
int sizeofitem = GinSizeOfDataPageItem(page); int sizeofitem = GinSizeOfDataPageItem(page);
int cnt = 0;
/* these must be static so they can be returned to caller */ /* these must be static so they can be returned to caller */
static XLogRecData rdata[3]; static XLogRecData rdata[3];
@ -401,32 +400,25 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE; data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE;
/* /*
* Prevent full page write if child's split occurs. That is needed to * For incomplete-split tracking, we need updateBlkno information and the
* remove incomplete splits while replaying WAL * inserted item even when we make a full page image of the page, so put
* * the buffer reference in a separate XLogRecData entry.
* data.updateBlkno contains new block number (of newly created right
* page) for recently splited page.
*/ */
if (data.updateBlkno == InvalidBlockNumber) rdata[0].buffer = buf;
{ rdata[0].buffer_std = FALSE;
rdata[0].buffer = buf; rdata[0].data = NULL;
rdata[0].buffer_std = FALSE; rdata[0].len = 0;
rdata[0].data = NULL; rdata[0].next = &rdata[1];
rdata[0].len = 0;
rdata[0].next = &rdata[1];
cnt++;
}
rdata[cnt].buffer = InvalidBuffer; rdata[1].buffer = InvalidBuffer;
rdata[cnt].data = (char *) &data; rdata[1].data = (char *) &data;
rdata[cnt].len = sizeof(ginxlogInsert); rdata[1].len = sizeof(ginxlogInsert);
rdata[cnt].next = &rdata[cnt + 1]; rdata[1].next = &rdata[2];
cnt++;
rdata[cnt].buffer = InvalidBuffer; rdata[2].buffer = InvalidBuffer;
rdata[cnt].data = (GinPageIsLeaf(page)) ? ((char *) (btree->items + btree->curitem)) : ((char *) &(btree->pitem)); rdata[2].data = (GinPageIsLeaf(page)) ? ((char *) (btree->items + btree->curitem)) : ((char *) &(btree->pitem));
rdata[cnt].len = sizeofitem; rdata[2].len = sizeofitem;
rdata[cnt].next = NULL; rdata[2].next = NULL;
if (GinPageIsLeaf(page)) if (GinPageIsLeaf(page))
{ {
@ -442,7 +434,7 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
btree->curitem++; btree->curitem++;
} }
data.nitem = btree->curitem - savedPos; data.nitem = btree->curitem - savedPos;
rdata[cnt].len = sizeofitem * data.nitem; rdata[2].len = sizeofitem * data.nitem;
} }
else else
{ {

View File

@ -486,7 +486,6 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prd
{ {
Page page = BufferGetPage(buf); Page page = BufferGetPage(buf);
OffsetNumber placed; OffsetNumber placed;
int cnt = 0;
/* these must be static so they can be returned to caller */ /* these must be static so they can be returned to caller */
static XLogRecData rdata[3]; static XLogRecData rdata[3];
@ -509,32 +508,25 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prd
data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE; data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE;
/* /*
* Prevent full page write if child's split occurs. That is needed to * For incomplete-split tracking, we need updateBlkno information and the
* remove incomplete splits while replaying WAL * inserted item even when we make a full page image of the page, so put
* * the buffer reference in a separate XLogRecData entry.
* data.updateBlkno contains new block number (of newly created right
* page) for recently splited page.
*/ */
if (data.updateBlkno == InvalidBlockNumber) rdata[0].buffer = buf;
{ rdata[0].buffer_std = TRUE;
rdata[0].buffer = buf; rdata[0].data = NULL;
rdata[0].buffer_std = TRUE; rdata[0].len = 0;
rdata[0].data = NULL; rdata[0].next = &rdata[1];
rdata[0].len = 0;
rdata[0].next = &rdata[1];
cnt++;
}
rdata[cnt].buffer = InvalidBuffer; rdata[1].buffer = InvalidBuffer;
rdata[cnt].data = (char *) &data; rdata[1].data = (char *) &data;
rdata[cnt].len = sizeof(ginxlogInsert); rdata[1].len = sizeof(ginxlogInsert);
rdata[cnt].next = &rdata[cnt + 1]; rdata[1].next = &rdata[2];
cnt++;
rdata[cnt].buffer = InvalidBuffer; rdata[2].buffer = InvalidBuffer;
rdata[cnt].data = (char *) btree->entry; rdata[2].data = (char *) btree->entry;
rdata[cnt].len = IndexTupleSize(btree->entry); rdata[2].len = IndexTupleSize(btree->entry);
rdata[cnt].next = NULL; rdata[2].next = NULL;
btree->entry = NULL; btree->entry = NULL;
} }