1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-05 02:22:28 +03:00

Defer flushing of SLRU files.

Previously, we called fsync() after writing out individual pg_xact,
pg_multixact and pg_commit_ts pages due to cache pressure, leading to
regular I/O stalls in user backends and recovery.  Collapse requests for
the same file into a single system call as part of the next checkpoint,
as we already did for relation files, using the infrastructure developed
by commit 3eb77eba.  This can cause a significant improvement to
recovery performance, especially when it's otherwise CPU-bound.

Hoist ProcessSyncRequests() up into CheckPointGuts() to make it clearer
that it applies to all the SLRU mini-buffer-pools as well as the main
buffer pool.  Rearrange things so that data collected in CheckpointStats
includes SLRU activity.

Also remove the Shutdown{CLOG,CommitTS,SUBTRANS,MultiXact}() functions,
because they were redundant after the shutdown checkpoint that
immediately precedes them.  (I'm not sure if they were ever needed, but
they aren't now.)

Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> (parts)
Tested-by: Jakub Wartak <Jakub.Wartak@tomtom.com>
Discussion: https://postgr.es/m/CA+hUKGLJ=84YT+NvhkEEDAuUtVHMfQ9i-N7k_o50JmQ6Rpj_OQ@mail.gmail.com
This commit is contained in:
Thomas Munro
2020-09-25 18:49:43 +12:00
parent ca7f8e2b86
commit dee663f784
16 changed files with 255 additions and 175 deletions

View File

@@ -2636,14 +2636,7 @@ PrintBufferLeakWarning(Buffer buffer)
void
CheckPointBuffers(int flags)
{
TRACE_POSTGRESQL_BUFFER_CHECKPOINT_START(flags);
CheckpointStats.ckpt_write_t = GetCurrentTimestamp();
BufferSync(flags);
CheckpointStats.ckpt_sync_t = GetCurrentTimestamp();
TRACE_POSTGRESQL_BUFFER_CHECKPOINT_SYNC_START();
ProcessSyncRequests();
CheckpointStats.ckpt_sync_end_t = GetCurrentTimestamp();
TRACE_POSTGRESQL_BUFFER_CHECKPOINT_DONE();
}

View File

@@ -821,9 +821,7 @@ SerialInit(void)
SerialSlruCtl->PagePrecedes = SerialPagePrecedesLogically;
SimpleLruInit(SerialSlruCtl, "Serial",
NUM_SERIAL_BUFFERS, 0, SerialSLRULock, "pg_serial",
LWTRANCHE_SERIAL_BUFFER);
/* Override default assumption that writes should be fsync'd */
SerialSlruCtl->do_fsync = false;
LWTRANCHE_SERIAL_BUFFER, SYNC_HANDLER_NONE);
/*
* Create or attach to the SerialControl structure.
@@ -1052,7 +1050,7 @@ CheckPointPredicate(void)
SimpleLruTruncate(SerialSlruCtl, tailPage);
/*
* Flush dirty SLRU pages to disk
* Write dirty SLRU pages to disk
*
* This is not actually necessary from a correctness point of view. We do
* it merely as a debugging aid.
@@ -1061,7 +1059,7 @@ CheckPointPredicate(void)
* before deleting the file in which they sit, which would be completely
* pointless.
*/
SimpleLruFlush(SerialSlruCtl, true);
SimpleLruWriteAll(SerialSlruCtl, true);
}
/*------------------------------------------------------------------------*/

View File

@@ -18,6 +18,9 @@
#include <fcntl.h>
#include <sys/file.h>
#include "access/commit_ts.h"
#include "access/clog.h"
#include "access/multixact.h"
#include "access/xlog.h"
#include "access/xlogutils.h"
#include "commands/tablespace.h"
@@ -90,12 +93,31 @@ typedef struct SyncOps
const FileTag *candidate);
} SyncOps;
/*
* These indexes must correspond to the values of the SyncRequestHandler enum.
*/
static const SyncOps syncsw[] = {
/* magnetic disk */
{
[SYNC_HANDLER_MD] = {
.sync_syncfiletag = mdsyncfiletag,
.sync_unlinkfiletag = mdunlinkfiletag,
.sync_filetagmatches = mdfiletagmatches
},
/* pg_xact */
[SYNC_HANDLER_CLOG] = {
.sync_syncfiletag = clogsyncfiletag
},
/* pg_commit_ts */
[SYNC_HANDLER_COMMIT_TS] = {
.sync_syncfiletag = committssyncfiletag
},
/* pg_multixact/offsets */
[SYNC_HANDLER_MULTIXACT_OFFSET] = {
.sync_syncfiletag = multixactoffsetssyncfiletag
},
/* pg_multixact/members */
[SYNC_HANDLER_MULTIXACT_MEMBER] = {
.sync_syncfiletag = multixactmemberssyncfiletag
}
};
@@ -505,8 +527,8 @@ RememberSyncRequest(const FileTag *ftag, SyncRequestType type)
(void *) ftag,
HASH_ENTER,
&found);
/* if new entry, initialize it */
if (!found)
/* if new entry, or was previously canceled, initialize it */
if (!found || entry->canceled)
{
entry->cycle_ctr = sync_cycle_ctr;
entry->canceled = false;