aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
authorFujii Masao <fujii@postgresql.org>2021-07-21 11:19:00 +0900
committerFujii Masao <fujii@postgresql.org>2021-07-21 11:19:00 +0900
commit7fcf2faf9c7dd473208fd6d5565f88d7f733782b (patch)
tree36a9f917da6e5d6a7199cc0ef40c227e0e7f038a /src/backend/access/transam/xlog.c
parentd9809bf8694c17e05537c5dd96cde3e67c02d52a (diff)
downloadpostgresql-7fcf2faf9c7dd473208fd6d5565f88d7f733782b.tar.gz
postgresql-7fcf2faf9c7dd473208fd6d5565f88d7f733782b.zip
Make XLOG_FPI_FOR_HINT records honor full_page_writes setting.
Commit 2c03216d83 changed XLOG_FPI_FOR_HINT records so that they always included full-page images even when full_page_writes was disabled. However, in this setting, they don't need to do that because hint bit updates don't need to be protected from torn writes. Therefore, this commit makes XLOG_FPI_FOR_HINT records honor full_page_writes setting. That is, XLOG_FPI_FOR_HINT records may include no full-page images if full_page_writes is disabled, and WAL replay of them does nothing. Reported-by: Zhang Wenjie Author: Kyotaro Horiguchi Reviewed-by: Fujii Masao Discussion: https://postgr.es/m/tencent_60F11973A111EED97A8596FFECC4A91ED405@qq.com
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 2ee95151392..3479402272b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -10148,7 +10148,10 @@ xlog_redo(XLogReaderState *record)
uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
XLogRecPtr lsn = record->EndRecPtr;
- /* in XLOG rmgr, backup blocks are only used by XLOG_FPI records */
+ /*
+ * In XLOG rmgr, backup blocks are only used by XLOG_FPI and
+ * XLOG_FPI_FOR_HINT records.
+ */
Assert(info == XLOG_FPI || info == XLOG_FPI_FOR_HINT ||
!XLogRecHasAnyBlockRefs(record));
@@ -10356,25 +10359,32 @@ xlog_redo(XLogReaderState *record)
else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
{
/*
- * Full-page image (FPI) records contain nothing else but a backup
- * block (or multiple backup blocks). Every block reference must
- * include a full-page image - otherwise there would be no point in
- * this record.
+ * XLOG_FPI records contain nothing else but one or more block
+ * references. Every block reference must include a full-page image
+ * even if full_page_writes was disabled when the record was generated
+ * - otherwise there would be no point in this record.
+ *
+ * XLOG_FPI_FOR_HINT records are generated when a page needs to be
+ * WAL-logged because of a hint bit update. They are only generated
+ * when checksums and/or wal_log_hints are enabled. They may include
+ * no full-page images if full_page_writes was disabled when they were
+ * generated. In this case there is nothing to do here.
*
* No recovery conflicts are generated by these generic records - if a
* resource manager needs to generate conflicts, it has to define a
* separate WAL record type and redo routine.
- *
- * XLOG_FPI_FOR_HINT records are generated when a page needs to be
- * WAL- logged because of a hint bit update. They are only generated
- * when checksums are enabled. There is no difference in handling
- * XLOG_FPI and XLOG_FPI_FOR_HINT records, they use a different info
- * code just to distinguish them for statistics purposes.
*/
for (uint8 block_id = 0; block_id <= record->max_block_id; block_id++)
{
Buffer buffer;
+ if (!XLogRecHasBlockImage(record, block_id))
+ {
+ if (info == XLOG_FPI)
+ elog(ERROR, "XLOG_FPI record did not contain a full-page image");
+ continue;
+ }
+
if (XLogReadBufferForRedo(record, block_id, &buffer) != BLK_RESTORED)
elog(ERROR, "unexpected XLogReadBufferForRedo result when restoring backup block");
UnlockReleaseBuffer(buffer);