]> granicus.if.org Git - postgresql/commit
Fix multiple bugs in index page locking during hot-standby WAL replay.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 14 Jan 2014 22:34:54 +0000 (17:34 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 14 Jan 2014 22:34:54 +0000 (17:34 -0500)
commitad2e041a3f4b0d3266b0848c0da6eadce7391316
treea65c3c5920e48451395dfaf1852c76e3183f0aa8
parent299498d6d11c851bab107313a4ca1bf2644881b6
Fix multiple bugs in index page locking during hot-standby WAL replay.

In ordinary operation, VACUUM must be careful to take a cleanup lock on
each leaf page of a btree index; this ensures that no indexscans could
still be "in flight" to heap tuples due to be deleted.  (Because of
possible index-tuple motion due to concurrent page splits, it's not enough
to lock only the pages we're deleting index tuples from.)  In Hot Standby,
the WAL replay process must likewise lock every leaf page.  There were
several bugs in the code for that:

* The replay scan might come across unused, all-zero pages in the index.
While btree_xlog_vacuum itself did the right thing (ie, nothing) with
such pages, xlogutils.c supposed that such pages must be corrupt and
would throw an error.  This accounts for various reports of replication
failures with "PANIC: WAL contains references to invalid pages".  To
fix, add a ReadBufferMode value that instructs XLogReadBufferExtended
not to complain when we're doing this.

* btree_xlog_vacuum performed the extra locking if standbyState ==
STANDBY_SNAPSHOT_READY, but that's not the correct test: we won't open up
for hot standby queries until the database has reached consistency, and
we don't want to do the extra locking till then either, for fear of reading
corrupted pages (which bufmgr.c would complain about).  Fix by exporting a
new function from xlog.c that will report whether we're actually in hot
standby replay mode.

* To ensure full coverage of the index in the replay scan, btvacuumscan
would emit a dummy WAL record for the last page of the index, if no
vacuuming work had been done on that page.  However, if the last page
of the index is all-zero, that would result in corruption of said page,
since the functions called on it weren't prepared to handle that case.
There's no need to lock any such pages, so change the logic to target
the last normal leaf page instead.

The first two of these bugs were diagnosed by Andres Freund, the other one
by me.  Fixes based on ideas from Heikki Linnakangas and myself.

This has been wrong since Hot Standby was introduced, so back-patch to 9.0.
src/backend/access/nbtree/nbtree.c
src/backend/access/nbtree/nbtxlog.c
src/backend/access/transam/xlog.c
src/backend/access/transam/xlogutils.c
src/backend/storage/buffer/bufmgr.c
src/include/access/xlog.h
src/include/storage/bufmgr.h