diff options
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r-- | src/backend/access/transam/xlog.c | 101 |
1 files changed, 96 insertions, 5 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 56e4d6fb022..1e9019156a5 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -77,6 +77,7 @@ #include "port/pg_iovec.h" #include "postmaster/bgwriter.h" #include "postmaster/startup.h" +#include "postmaster/walsummarizer.h" #include "postmaster/walwriter.h" #include "replication/logical.h" #include "replication/origin.h" @@ -3592,6 +3593,43 @@ XLogGetLastRemovedSegno(void) return lastRemovedSegNo; } +/* + * Return the oldest WAL segment on the given TLI that still exists in + * XLOGDIR, or 0 if none. + */ +XLogSegNo +XLogGetOldestSegno(TimeLineID tli) +{ + DIR *xldir; + struct dirent *xlde; + XLogSegNo oldest_segno = 0; + + xldir = AllocateDir(XLOGDIR); + while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL) + { + TimeLineID file_tli; + XLogSegNo file_segno; + + /* Ignore files that are not XLOG segments. */ + if (!IsXLogFileName(xlde->d_name)) + continue; + + /* Parse filename to get TLI and segno. */ + XLogFromFileName(xlde->d_name, &file_tli, &file_segno, + wal_segment_size); + + /* Ignore anything that's not from the TLI of interest. */ + if (tli != file_tli) + continue; + + /* If it's the oldest so far, update oldest_segno. */ + if (oldest_segno == 0 || file_segno < oldest_segno) + oldest_segno = file_segno; + } + + FreeDir(xldir); + return oldest_segno; +} /* * Update the last removed segno pointer in shared memory, to reflect that the @@ -3872,8 +3910,8 @@ RemoveXlogFile(const struct dirent *segment_de, } /* - * Verify whether pg_wal and pg_wal/archive_status exist. - * If the latter does not exist, recreate it. + * Verify whether pg_wal, pg_wal/archive_status, and pg_wal/summaries exist. + * If the latter do not exist, recreate them. * * It is not the goal of this function to verify the contents of these * directories, but to help in cases where someone has performed a cluster @@ -3916,6 +3954,26 @@ ValidateXLOGDirectoryStructure(void) (errmsg("could not create missing directory \"%s\": %m", path))); } + + /* Check for summaries */ + snprintf(path, MAXPGPATH, XLOGDIR "/summaries"); + if (stat(path, &stat_buf) == 0) + { + /* Check for weird cases where it exists but isn't a directory */ + if (!S_ISDIR(stat_buf.st_mode)) + ereport(FATAL, + (errmsg("required WAL directory \"%s\" does not exist", + path))); + } + else + { + ereport(LOG, + (errmsg("creating missing WAL directory \"%s\"", path))); + if (MakePGDirectory(path) < 0) + ereport(FATAL, + (errmsg("could not create missing directory \"%s\": %m", + path))); + } } /* @@ -5243,9 +5301,9 @@ StartupXLOG(void) #endif /* - * Verify that pg_wal and pg_wal/archive_status exist. In cases where - * someone has performed a copy for PITR, these directories may have been - * excluded and need to be re-created. + * Verify that pg_wal, pg_wal/archive_status, and pg_wal/summaries exist. + * In cases where someone has performed a copy for PITR, these directories + * may have been excluded and need to be re-created. */ ValidateXLOGDirectoryStructure(); @@ -6963,6 +7021,25 @@ CreateCheckPoint(int flags) END_CRIT_SECTION(); /* + * WAL summaries end when the next XLOG_CHECKPOINT_REDO or + * XLOG_CHECKPOINT_SHUTDOWN record is reached. This is the first point + * where (a) we're not inside of a critical section and (b) we can be + * certain that the relevant record has been flushed to disk, which must + * happen before it can be summarized. + * + * If this is a shutdown checkpoint, then this happens reasonably + * promptly: we've only just inserted and flushed the + * XLOG_CHECKPOINT_SHUTDOWN record. If this is not a shutdown checkpoint, + * then this might not be very prompt at all: the XLOG_CHECKPOINT_REDO + * record was written before we began flushing data to disk, and that + * could be many minutes ago at this point. However, we don't XLogFlush() + * after inserting that record, so we're not guaranteed that it's on disk + * until after the above call that flushes the XLOG_CHECKPOINT_ONLINE + * record. + */ + SetWalSummarizerLatch(); + + /* * Let smgr do post-checkpoint cleanup (eg, deleting old files). */ SyncPostCheckpoint(); @@ -7636,6 +7713,20 @@ KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo) } } + /* + * If WAL summarization is in use, don't remove WAL that has yet to be + * summarized. + */ + keep = GetOldestUnsummarizedLSN(NULL, NULL, false); + if (keep != InvalidXLogRecPtr) + { + XLogSegNo unsummarized_segno; + + XLByteToSeg(keep, unsummarized_segno, wal_segment_size); + if (unsummarized_segno < segno) + segno = unsummarized_segno; + } + /* but, keep at least wal_keep_size if that's set */ if (wal_keep_size_mb > 0) { |