mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
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
This commit is contained in:
@ -10148,7 +10148,10 @@ xlog_redo(XLogReaderState *record)
|
|||||||
uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
|
uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
|
||||||
XLogRecPtr lsn = record->EndRecPtr;
|
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 ||
|
Assert(info == XLOG_FPI || info == XLOG_FPI_FOR_HINT ||
|
||||||
!XLogRecHasAnyBlockRefs(record));
|
!XLogRecHasAnyBlockRefs(record));
|
||||||
|
|
||||||
@ -10356,25 +10359,32 @@ xlog_redo(XLogReaderState *record)
|
|||||||
else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
|
else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Full-page image (FPI) records contain nothing else but a backup
|
* XLOG_FPI records contain nothing else but one or more block
|
||||||
* block (or multiple backup blocks). Every block reference must
|
* references. Every block reference must include a full-page image
|
||||||
* include a full-page image - otherwise there would be no point in
|
* even if full_page_writes was disabled when the record was generated
|
||||||
* this record.
|
* - 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
|
* No recovery conflicts are generated by these generic records - if a
|
||||||
* resource manager needs to generate conflicts, it has to define a
|
* resource manager needs to generate conflicts, it has to define a
|
||||||
* separate WAL record type and redo routine.
|
* 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++)
|
for (uint8 block_id = 0; block_id <= record->max_block_id; block_id++)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
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)
|
if (XLogReadBufferForRedo(record, block_id, &buffer) != BLK_RESTORED)
|
||||||
elog(ERROR, "unexpected XLogReadBufferForRedo result when restoring backup block");
|
elog(ERROR, "unexpected XLogReadBufferForRedo result when restoring backup block");
|
||||||
UnlockReleaseBuffer(buffer);
|
UnlockReleaseBuffer(buffer);
|
||||||
|
@ -287,8 +287,6 @@ XLogRegisterBlock(uint8 block_id, RelFileNode *rnode, ForkNumber forknum,
|
|||||||
{
|
{
|
||||||
registered_buffer *regbuf;
|
registered_buffer *regbuf;
|
||||||
|
|
||||||
/* This is currently only used to WAL-log a full-page image of a page */
|
|
||||||
Assert(flags & REGBUF_FORCE_IMAGE);
|
|
||||||
Assert(begininsert_called);
|
Assert(begininsert_called);
|
||||||
|
|
||||||
if (block_id >= max_registered_block_id)
|
if (block_id >= max_registered_block_id)
|
||||||
@ -995,7 +993,7 @@ XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
|
|||||||
|
|
||||||
if (lsn <= RedoRecPtr)
|
if (lsn <= RedoRecPtr)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags = 0;
|
||||||
PGAlignedBlock copied_buffer;
|
PGAlignedBlock copied_buffer;
|
||||||
char *origdata = (char *) BufferGetBlock(buffer);
|
char *origdata = (char *) BufferGetBlock(buffer);
|
||||||
RelFileNode rnode;
|
RelFileNode rnode;
|
||||||
@ -1022,7 +1020,6 @@ XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
|
|||||||
|
|
||||||
XLogBeginInsert();
|
XLogBeginInsert();
|
||||||
|
|
||||||
flags = REGBUF_FORCE_IMAGE;
|
|
||||||
if (buffer_std)
|
if (buffer_std)
|
||||||
flags |= REGBUF_STANDARD;
|
flags |= REGBUF_STANDARD;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user