Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b5f58cf

Browse files
committed
Convert gist to compute page level xid horizon on primary.
Due to parallel development, gist added the missing conflict information in c952eae, while 558a916 moved that computation to the primary for the index types that already had it. Thus adapt gist to also compute on the primary, using index_compute_xid_horizon_for_tuples() instead of its own copy of the logic. This also adds pg_waldump support for XLOG_GIST_DELETE records, which previously was not properly present. Bumps WAL version. Author: Andres Freund Discussion: https://postgr.es/m/20190406050243.bszosdg4buvabfrt@alap3.anarazel.de
1 parent b804c18 commit b5f58cf

File tree

6 files changed

+18
-157
lines changed

6 files changed

+18
-157
lines changed

src/backend/access/gist/gist.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,7 @@ gistprunepage(Relation rel, Page page, Buffer buffer, Relation heapRel)
16161616
int ndeletable = 0;
16171617
OffsetNumber offnum,
16181618
maxoff;
1619+
TransactionId latestRemovedXid = InvalidTransactionId;
16191620

16201621
Assert(GistPageIsLeaf(page));
16211622

@@ -1634,6 +1635,11 @@ gistprunepage(Relation rel, Page page, Buffer buffer, Relation heapRel)
16341635
deletable[ndeletable++] = offnum;
16351636
}
16361637

1638+
if (XLogStandbyInfoActive() && RelationNeedsWAL(rel))
1639+
latestRemovedXid =
1640+
index_compute_xid_horizon_for_tuples(rel, heapRel, buffer,
1641+
deletable, ndeletable);
1642+
16371643
if (ndeletable > 0)
16381644
{
16391645
START_CRIT_SECTION();
@@ -1658,7 +1664,7 @@ gistprunepage(Relation rel, Page page, Buffer buffer, Relation heapRel)
16581664

16591665
recptr = gistXLogDelete(buffer,
16601666
deletable, ndeletable,
1661-
heapRel->rd_node);
1667+
latestRemovedXid);
16621668

16631669
PageSetLSN(page, recptr);
16641670
}

src/backend/access/gist/gistxlog.c

Lines changed: 3 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -165,152 +165,6 @@ gistRedoPageUpdateRecord(XLogReaderState *record)
165165
UnlockReleaseBuffer(buffer);
166166
}
167167

168-
/*
169-
* Get the latestRemovedXid from the heap pages pointed at by the index
170-
* tuples being deleted. See also btree_xlog_delete_get_latestRemovedXid,
171-
* on which this function is based.
172-
*/
173-
static TransactionId
174-
gistRedoDeleteRecordGetLatestRemovedXid(XLogReaderState *record)
175-
{
176-
gistxlogDelete *xlrec = (gistxlogDelete *) XLogRecGetData(record);
177-
OffsetNumber *todelete;
178-
Buffer ibuffer,
179-
hbuffer;
180-
Page ipage,
181-
hpage;
182-
RelFileNode rnode;
183-
BlockNumber blkno;
184-
ItemId iitemid,
185-
hitemid;
186-
IndexTuple itup;
187-
HeapTupleHeader htuphdr;
188-
BlockNumber hblkno;
189-
OffsetNumber hoffnum;
190-
TransactionId latestRemovedXid = InvalidTransactionId;
191-
int i;
192-
193-
/*
194-
* If there's nothing running on the standby we don't need to derive a
195-
* full latestRemovedXid value, so use a fast path out of here. This
196-
* returns InvalidTransactionId, and so will conflict with all HS
197-
* transactions; but since we just worked out that that's zero people,
198-
* it's OK.
199-
*
200-
* XXX There is a race condition here, which is that a new backend might
201-
* start just after we look. If so, it cannot need to conflict, but this
202-
* coding will result in throwing a conflict anyway.
203-
*/
204-
if (CountDBBackends(InvalidOid) == 0)
205-
return latestRemovedXid;
206-
207-
/*
208-
* In what follows, we have to examine the previous state of the index
209-
* page, as well as the heap page(s) it points to. This is only valid if
210-
* WAL replay has reached a consistent database state; which means that
211-
* the preceding check is not just an optimization, but is *necessary*. We
212-
* won't have let in any user sessions before we reach consistency.
213-
*/
214-
if (!reachedConsistency)
215-
elog(PANIC, "gistRedoDeleteRecordGetLatestRemovedXid: cannot operate with inconsistent data");
216-
217-
/*
218-
* Get index page. If the DB is consistent, this should not fail, nor
219-
* should any of the heap page fetches below. If one does, we return
220-
* InvalidTransactionId to cancel all HS transactions. That's probably
221-
* overkill, but it's safe, and certainly better than panicking here.
222-
*/
223-
XLogRecGetBlockTag(record, 0, &rnode, NULL, &blkno);
224-
ibuffer = XLogReadBufferExtended(rnode, MAIN_FORKNUM, blkno, RBM_NORMAL);
225-
if (!BufferIsValid(ibuffer))
226-
return InvalidTransactionId;
227-
LockBuffer(ibuffer, BUFFER_LOCK_EXCLUSIVE);
228-
ipage = (Page) BufferGetPage(ibuffer);
229-
230-
/*
231-
* Loop through the deleted index items to obtain the TransactionId from
232-
* the heap items they point to.
233-
*/
234-
todelete = (OffsetNumber *) ((char *) xlrec + SizeOfGistxlogDelete);
235-
236-
for (i = 0; i < xlrec->ntodelete; i++)
237-
{
238-
/*
239-
* Identify the index tuple about to be deleted
240-
*/
241-
iitemid = PageGetItemId(ipage, todelete[i]);
242-
itup = (IndexTuple) PageGetItem(ipage, iitemid);
243-
244-
/*
245-
* Locate the heap page that the index tuple points at
246-
*/
247-
hblkno = ItemPointerGetBlockNumber(&(itup->t_tid));
248-
hbuffer = XLogReadBufferExtended(xlrec->hnode, MAIN_FORKNUM, hblkno, RBM_NORMAL);
249-
if (!BufferIsValid(hbuffer))
250-
{
251-
UnlockReleaseBuffer(ibuffer);
252-
return InvalidTransactionId;
253-
}
254-
LockBuffer(hbuffer, BUFFER_LOCK_SHARE);
255-
hpage = (Page) BufferGetPage(hbuffer);
256-
257-
/*
258-
* Look up the heap tuple header that the index tuple points at by
259-
* using the heap node supplied with the xlrec. We can't use
260-
* heap_fetch, since it uses ReadBuffer rather than XLogReadBuffer.
261-
* Note that we are not looking at tuple data here, just headers.
262-
*/
263-
hoffnum = ItemPointerGetOffsetNumber(&(itup->t_tid));
264-
hitemid = PageGetItemId(hpage, hoffnum);
265-
266-
/*
267-
* Follow any redirections until we find something useful.
268-
*/
269-
while (ItemIdIsRedirected(hitemid))
270-
{
271-
hoffnum = ItemIdGetRedirect(hitemid);
272-
hitemid = PageGetItemId(hpage, hoffnum);
273-
CHECK_FOR_INTERRUPTS();
274-
}
275-
276-
/*
277-
* If the heap item has storage, then read the header and use that to
278-
* set latestRemovedXid.
279-
*
280-
* Some LP_DEAD items may not be accessible, so we ignore them.
281-
*/
282-
if (ItemIdHasStorage(hitemid))
283-
{
284-
htuphdr = (HeapTupleHeader) PageGetItem(hpage, hitemid);
285-
286-
HeapTupleHeaderAdvanceLatestRemovedXid(htuphdr, &latestRemovedXid);
287-
}
288-
else if (ItemIdIsDead(hitemid))
289-
{
290-
/*
291-
* Conjecture: if hitemid is dead then it had xids before the xids
292-
* marked on LP_NORMAL items. So we just ignore this item and move
293-
* onto the next, for the purposes of calculating
294-
* latestRemovedxids.
295-
*/
296-
}
297-
else
298-
Assert(!ItemIdIsUsed(hitemid));
299-
300-
UnlockReleaseBuffer(hbuffer);
301-
}
302-
303-
UnlockReleaseBuffer(ibuffer);
304-
305-
/*
306-
* If all heap tuples were LP_DEAD then we will be returning
307-
* InvalidTransactionId here, which avoids conflicts. This matches
308-
* existing logic which assumes that LP_DEAD tuples must already be older
309-
* than the latestRemovedXid on the cleanup record that set them as
310-
* LP_DEAD, hence must already have generated a conflict.
311-
*/
312-
return latestRemovedXid;
313-
}
314168

315169
/*
316170
* redo delete on gist index page to remove tuples marked as DEAD during index
@@ -337,12 +191,11 @@ gistRedoDeleteRecord(XLogReaderState *record)
337191
*/
338192
if (InHotStandby)
339193
{
340-
TransactionId latestRemovedXid = gistRedoDeleteRecordGetLatestRemovedXid(record);
341194
RelFileNode rnode;
342195

343196
XLogRecGetBlockTag(record, 0, &rnode, NULL, NULL);
344197

345-
ResolveRecoveryConflictWithSnapshot(latestRemovedXid, rnode);
198+
ResolveRecoveryConflictWithSnapshot(xldata->latestRemovedXid, rnode);
346199
}
347200

348201
if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
@@ -800,12 +653,12 @@ gistXLogUpdate(Buffer buffer,
800653
*/
801654
XLogRecPtr
802655
gistXLogDelete(Buffer buffer, OffsetNumber *todelete, int ntodelete,
803-
RelFileNode hnode)
656+
TransactionId latestRemovedXid)
804657
{
805658
gistxlogDelete xlrec;
806659
XLogRecPtr recptr;
807660

808-
xlrec.hnode = hnode;
661+
xlrec.latestRemovedXid = latestRemovedXid;
809662
xlrec.ntodelete = ntodelete;
810663

811664
XLogBeginInsert();

src/backend/access/rmgrdesc/gistdesc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ out_gistxlogPageReuse(StringInfo buf, gistxlogPageReuse *xlrec)
3333
}
3434

3535
static void
36-
out_gistxlogDelete(StringInfo buf, gistxlogPageUpdate *xlrec)
36+
out_gistxlogDelete(StringInfo buf, gistxlogDelete *xlrec)
3737
{
38+
appendStringInfo(buf, "delete: latestRemovedXid %u, nitems: %u",
39+
xlrec->latestRemovedXid, xlrec->ntodelete);
40+
3841
}
3942

4043
static void
@@ -66,7 +69,7 @@ gist_desc(StringInfo buf, XLogReaderState *record)
6669
out_gistxlogPageReuse(buf, (gistxlogPageReuse *) rec);
6770
break;
6871
case XLOG_GIST_DELETE:
69-
out_gistxlogDelete(buf, (gistxlogPageUpdate *) rec);
72+
out_gistxlogDelete(buf, (gistxlogDelete *) rec);
7073
break;
7174
case XLOG_GIST_PAGE_SPLIT:
7275
out_gistxlogPageSplit(buf, (gistxlogPageSplit *) rec);

src/include/access/gist_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ extern XLogRecPtr gistXLogUpdate(Buffer buffer,
431431
Buffer leftchild);
432432

433433
extern XLogRecPtr gistXLogDelete(Buffer buffer, OffsetNumber *todelete,
434-
int ntodelete, RelFileNode hnode);
434+
int ntodelete, TransactionId latestRemovedXid);
435435

436436
extern XLogRecPtr gistXLogSplit(bool page_is_leaf,
437437
SplitedPageLayout *dist,

src/include/access/gistxlog.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ typedef struct gistxlogPageUpdate
4747
*/
4848
typedef struct gistxlogDelete
4949
{
50-
RelFileNode hnode; /* RelFileNode of the heap the index currently
51-
* points at */
50+
TransactionId latestRemovedXid;
5251
uint16 ntodelete; /* number of deleted offsets */
5352

5453
/*

src/include/access/xlog_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
/*
3232
* Each page of XLOG file has a header like this:
3333
*/
34-
#define XLOG_PAGE_MAGIC 0xD100 /* can be used as WAL version indicator */
34+
#define XLOG_PAGE_MAGIC 0xD101 /* can be used as WAL version indicator */
3535

3636
typedef struct XLogPageHeaderData
3737
{

0 commit comments

Comments
 (0)