Do not take a full-page image for REGBUF_NO_CHANGE buffers A buffer registered with REGBUF_NO_CHANGE is not modified by the record and, in the case of the hash index AM, may be held with only a pin (no content lock). The hash index code registers the primary bucket page this way in hashbucketcleanup(), _hash_freeovflpage() and _hash_squeezebucket(), solely to force a cleanup lock on that block during replay.
When wal_consistency_checking includes "hash", XLogRecordAssemble() included a full-page image for block only pinned, because XLR_CHECK_CONSISTENCY forces an image regardless of REGBUF_NO_IMAGE. The record CRC is then computed over the image while a concurrent backend, which legitimately holds nothing stronger than a pin on that page, could modify it before the record is copied into the WAL buffers. This would result is an intermittent "incorrect resource manager data checksum in record" failure on a standby. As of this commit, never take an image for a REGBUF_NO_CHANGE buffer, even under XLR_CHECK_CONSISTENCY. There is no need to do a consistency check on a block not changed by a record. verifyBackupPageConsistency() is taught to skip a registered block that carries no image rather than asserting one should be present. REGBUF_NO_CHANGE exists since 00d7fb5e2e39, so backpatch down to v17. On older branches, the CRC problem can be reproduced as well, but we lack the mechanism to check how a buffer is handled by the code assembling a record. Per discussion, the long term picture should be to fix the hash index AM so as REGBUF_NO_CHANGE is removed. This would be a HEAD-only change. Reported-by: Alexander Lakhin <[email protected]> Diagnosed-by: Thomas Munro <[email protected]> Author: Greg Burd <[email protected]> Discussion: https://postgr.es/m/ats4pi-RM0Uom0T9@floki Backpatch-through: 17 Branch ------ REL_19_STABLE Details ------- https://git.postgresql.org/pg/commitdiff/4232bf96ec369599957e5c87b3cae69d8d275e8b Modified Files -------------- src/backend/access/transam/README | 5 +++++ src/backend/access/transam/xloginsert.c | 7 ++++++- src/backend/access/transam/xlogrecovery.c | 7 ++++++- src/include/access/xloginsert.h | 4 +++- 4 files changed, 20 insertions(+), 3 deletions(-)
