summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-07-09 19:26:19 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2018-07-09 19:26:19 -0400
commit568995be6703593c01cbb4346c4ede3b44e168a9 (patch)
tree46969fef8dc3c5920e9dfce4924811b8ddc7796b /src
parentccc286da1d35b5d57a1e3322027905c00507d38f (diff)
Avoid emitting a bogus WAL record when recycling an all-zero btree page.
Commit fafa374f2 caused _bt_getbuf() to possibly emit a WAL record for a page that it was about to recycle. However, it failed to distinguish all-zero pages from dead pages, which is important because only the latter have valid btpo.xact values, or indeed any special space at all. Recycling an all-zero page with XLogStandbyInfoActive() enabled therefore led to an Assert failure, or to emission of a WAL record containing a bogus cutoff XID, which might lead to unnecessary query cancellations on hot standby servers. Per reports from Antonin Houska and 自己. Amit Kapila was first to propose this fix, and Robert Haas, myself, and Kyotaro Horiguchi reviewed it at various times. This is an old bug, so back-patch to all supported branches. Discussion: https://postgr.es/m/2628.1474272158@localhost Discussion: https://postgr.es/m/48875502.f4a0.1635f0c27b0.Coremail.zoulx1982@163.com
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/nbtree/nbtpage.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index eb9d9610366..f3b99df2cac 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -622,9 +622,14 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
/*
* If we are generating WAL for Hot Standby then create a
* WAL record that will allow us to conflict with queries
- * running on standby.
+ * running on standby, in case they have snapshots older
+ * than btpo.xact. This can only apply if the page does
+ * have a valid btpo.xact value, ie not if it's new. (We
+ * must check that because an all-zero page has no special
+ * space.)
*/
- if (XLogStandbyInfoActive() && RelationNeedsWAL(rel))
+ if (XLogStandbyInfoActive() && RelationNeedsWAL(rel) &&
+ !PageIsNew(page))
{
BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
@@ -737,7 +742,10 @@ _bt_pageinit(Page page, Size size)
* _bt_page_recyclable() -- Is an existing page recyclable?
*
* This exists to make sure _bt_getbuf and btvacuumscan have the same
- * policy about whether a page is safe to re-use.
+ * policy about whether a page is safe to re-use. But note that _bt_getbuf
+ * knows enough to distinguish the PageIsNew condition from the other one.
+ * At some point it might be appropriate to redesign this to have a three-way
+ * result value.
*/
bool
_bt_page_recyclable(Page page)