]> granicus.if.org Git - postgresql/commitdiff
BRIN revmap pages are not standard pages ...
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 9 Jan 2017 21:19:29 +0000 (18:19 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 9 Jan 2017 21:19:29 +0000 (18:19 -0300)
... and therefore we ought not to tell XLogRegisterBuffer the opposite,
when writing XLog for a brin update that moves the index tuple to a
different page.  Otherwise, xlog insertion would try to "compress the
hole" when producing a full-page image for it; but since we don't update
pd_lower/upper, the hole covers the whole page.  On WAL replay, the
revmap page becomes empty and so the entire portion of the index is
useless and needs to be recomputed.

This is low-probability: a BRIN update only moves an index tuple to a
different page when the summary tuple is larger than the existing one,
which doesn't happen with fixed-width datatypes.  Also, the revmap
page must be first after a checkpoint.

Report and patch: Kuntal Ghosh
Bug is alleged to have detected by a WAL-consistency-checking tool.
Discussion: https://postgr.es/m/CAGz5QCJ=00UQjScSEFbV=0qO5ShTZB9WWz_Fm7+Wd83zPs9Geg@mail.gmail.com

I posted a test case demonstrating the problem, but I'm refraining from
adding it to the test suite; if the WAL consistency tool makes it in,
that will be a better way to catch this from regressing.  (We should
definitely have someting that causes not-same-page updates, though.)

src/backend/access/brin/brin_pageops.c

index 08b358914056a358ec8ae80d66f228710350c3b7..da94efc61cad5d4392dcb8da9d3f968777571570 100644 (file)
@@ -287,7 +287,7 @@ brin_doupdate(Relation idxrel, BlockNumber pagesPerRange,
                        XLogRegisterBufData(0, (char *) newtup, newsz);
 
                        /* revmap page */
-                       XLogRegisterBuffer(1, revmapbuf, REGBUF_STANDARD);
+                       XLogRegisterBuffer(1, revmapbuf, 0);
 
                        /* old page */
                        XLogRegisterBuffer(2, oldbuf, REGBUF_STANDARD);