|
77 | 77 | #include "port/pg_iovec.h"
|
78 | 78 | #include "postmaster/bgwriter.h"
|
79 | 79 | #include "postmaster/startup.h"
|
| 80 | +#include "postmaster/walsummarizer.h" |
80 | 81 | #include "postmaster/walwriter.h"
|
81 | 82 | #include "replication/logical.h"
|
82 | 83 | #include "replication/origin.h"
|
@@ -3592,6 +3593,43 @@ XLogGetLastRemovedSegno(void)
|
3592 | 3593 | return lastRemovedSegNo;
|
3593 | 3594 | }
|
3594 | 3595 |
|
| 3596 | +/* |
| 3597 | + * Return the oldest WAL segment on the given TLI that still exists in |
| 3598 | + * XLOGDIR, or 0 if none. |
| 3599 | + */ |
| 3600 | +XLogSegNo |
| 3601 | +XLogGetOldestSegno(TimeLineID tli) |
| 3602 | +{ |
| 3603 | + DIR *xldir; |
| 3604 | + struct dirent *xlde; |
| 3605 | + XLogSegNo oldest_segno = 0; |
| 3606 | + |
| 3607 | + xldir = AllocateDir(XLOGDIR); |
| 3608 | + while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL) |
| 3609 | + { |
| 3610 | + TimeLineID file_tli; |
| 3611 | + XLogSegNo file_segno; |
| 3612 | + |
| 3613 | + /* Ignore files that are not XLOG segments. */ |
| 3614 | + if (!IsXLogFileName(xlde->d_name)) |
| 3615 | + continue; |
| 3616 | + |
| 3617 | + /* Parse filename to get TLI and segno. */ |
| 3618 | + XLogFromFileName(xlde->d_name, &file_tli, &file_segno, |
| 3619 | + wal_segment_size); |
| 3620 | + |
| 3621 | + /* Ignore anything that's not from the TLI of interest. */ |
| 3622 | + if (tli != file_tli) |
| 3623 | + continue; |
| 3624 | + |
| 3625 | + /* If it's the oldest so far, update oldest_segno. */ |
| 3626 | + if (oldest_segno == 0 || file_segno < oldest_segno) |
| 3627 | + oldest_segno = file_segno; |
| 3628 | + } |
| 3629 | + |
| 3630 | + FreeDir(xldir); |
| 3631 | + return oldest_segno; |
| 3632 | +} |
3595 | 3633 |
|
3596 | 3634 | /*
|
3597 | 3635 | * Update the last removed segno pointer in shared memory, to reflect that the
|
@@ -3872,8 +3910,8 @@ RemoveXlogFile(const struct dirent *segment_de,
|
3872 | 3910 | }
|
3873 | 3911 |
|
3874 | 3912 | /*
|
3875 |
| - * Verify whether pg_wal and pg_wal/archive_status exist. |
3876 |
| - * If the latter does not exist, recreate it. |
| 3913 | + * Verify whether pg_wal, pg_wal/archive_status, and pg_wal/summaries exist. |
| 3914 | + * If the latter do not exist, recreate them. |
3877 | 3915 | *
|
3878 | 3916 | * It is not the goal of this function to verify the contents of these
|
3879 | 3917 | * directories, but to help in cases where someone has performed a cluster
|
@@ -3916,6 +3954,26 @@ ValidateXLOGDirectoryStructure(void)
|
3916 | 3954 | (errmsg("could not create missing directory \"%s\": %m",
|
3917 | 3955 | path)));
|
3918 | 3956 | }
|
| 3957 | + |
| 3958 | + /* Check for summaries */ |
| 3959 | + snprintf(path, MAXPGPATH, XLOGDIR "/summaries"); |
| 3960 | + if (stat(path, &stat_buf) == 0) |
| 3961 | + { |
| 3962 | + /* Check for weird cases where it exists but isn't a directory */ |
| 3963 | + if (!S_ISDIR(stat_buf.st_mode)) |
| 3964 | + ereport(FATAL, |
| 3965 | + (errmsg("required WAL directory \"%s\" does not exist", |
| 3966 | + path))); |
| 3967 | + } |
| 3968 | + else |
| 3969 | + { |
| 3970 | + ereport(LOG, |
| 3971 | + (errmsg("creating missing WAL directory \"%s\"", path))); |
| 3972 | + if (MakePGDirectory(path) < 0) |
| 3973 | + ereport(FATAL, |
| 3974 | + (errmsg("could not create missing directory \"%s\": %m", |
| 3975 | + path))); |
| 3976 | + } |
3919 | 3977 | }
|
3920 | 3978 |
|
3921 | 3979 | /*
|
@@ -5243,9 +5301,9 @@ StartupXLOG(void)
|
5243 | 5301 | #endif
|
5244 | 5302 |
|
5245 | 5303 | /*
|
5246 |
| - * Verify that pg_wal and pg_wal/archive_status exist. In cases where |
5247 |
| - * someone has performed a copy for PITR, these directories may have been |
5248 |
| - * excluded and need to be re-created. |
| 5304 | + * Verify that pg_wal, pg_wal/archive_status, and pg_wal/summaries exist. |
| 5305 | + * In cases where someone has performed a copy for PITR, these directories |
| 5306 | + * may have been excluded and need to be re-created. |
5249 | 5307 | */
|
5250 | 5308 | ValidateXLOGDirectoryStructure();
|
5251 | 5309 |
|
@@ -6962,6 +7020,25 @@ CreateCheckPoint(int flags)
|
6962 | 7020 | */
|
6963 | 7021 | END_CRIT_SECTION();
|
6964 | 7022 |
|
| 7023 | + /* |
| 7024 | + * WAL summaries end when the next XLOG_CHECKPOINT_REDO or |
| 7025 | + * XLOG_CHECKPOINT_SHUTDOWN record is reached. This is the first point |
| 7026 | + * where (a) we're not inside of a critical section and (b) we can be |
| 7027 | + * certain that the relevant record has been flushed to disk, which must |
| 7028 | + * happen before it can be summarized. |
| 7029 | + * |
| 7030 | + * If this is a shutdown checkpoint, then this happens reasonably |
| 7031 | + * promptly: we've only just inserted and flushed the |
| 7032 | + * XLOG_CHECKPOINT_SHUTDOWN record. If this is not a shutdown checkpoint, |
| 7033 | + * then this might not be very prompt at all: the XLOG_CHECKPOINT_REDO |
| 7034 | + * record was written before we began flushing data to disk, and that |
| 7035 | + * could be many minutes ago at this point. However, we don't XLogFlush() |
| 7036 | + * after inserting that record, so we're not guaranteed that it's on disk |
| 7037 | + * until after the above call that flushes the XLOG_CHECKPOINT_ONLINE |
| 7038 | + * record. |
| 7039 | + */ |
| 7040 | + SetWalSummarizerLatch(); |
| 7041 | + |
6965 | 7042 | /*
|
6966 | 7043 | * Let smgr do post-checkpoint cleanup (eg, deleting old files).
|
6967 | 7044 | */
|
@@ -7636,6 +7713,20 @@ KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
|
7636 | 7713 | }
|
7637 | 7714 | }
|
7638 | 7715 |
|
| 7716 | + /* |
| 7717 | + * If WAL summarization is in use, don't remove WAL that has yet to be |
| 7718 | + * summarized. |
| 7719 | + */ |
| 7720 | + keep = GetOldestUnsummarizedLSN(NULL, NULL, false); |
| 7721 | + if (keep != InvalidXLogRecPtr) |
| 7722 | + { |
| 7723 | + XLogSegNo unsummarized_segno; |
| 7724 | + |
| 7725 | + XLByteToSeg(keep, unsummarized_segno, wal_segment_size); |
| 7726 | + if (unsummarized_segno < segno) |
| 7727 | + segno = unsummarized_segno; |
| 7728 | + } |
| 7729 | + |
7639 | 7730 | /* but, keep at least wal_keep_size if that's set */
|
7640 | 7731 | if (wal_keep_size_mb > 0)
|
7641 | 7732 | {
|
|
0 commit comments