v4-0001-pg_rewind-wal-deletion.patch
text/x-patch
Filename: v4-0001-pg_rewind-wal-deletion.patch
Type: text/x-patch
Part: 0
Patch
Format: format-patch
Series: patch v4-0001
Subject: Be more picky with WAL segment deletion in pg_rewind
| File | + | − |
|---|---|---|
| src/bin/pg_rewind/filemap.c | 18 | 1 |
| src/bin/pg_rewind/filemap.h | 1 | 0 |
| src/bin/pg_rewind/parsexlog.c | 22 | 0 |
| src/bin/pg_rewind/pg_rewind.c | 3 | 3 |
From 1a8504419f7fafc04443c09d86807dccffc750f8 Mon Sep 17 00:00:00 2001
From: Alexander Kukushkin <cyberdemn@gmail.com>
Date: Wed, 23 Aug 2023 13:40:47 +0200
Subject: [PATCH v4] Be more picky with WAL segment deletion in pg_rewind
Make pg_rewind to be a bit wiser in terms of creating filemap:
preserve on the target all WAL segments that contain records between the
last common checkpoint and the point of divergence.
Co-authored-by: Polina Bungina <bungina@gmail.com>
---
src/bin/pg_rewind/filemap.c | 19 ++++++++++++++++++-
src/bin/pg_rewind/filemap.h | 1 +
src/bin/pg_rewind/parsexlog.c | 22 ++++++++++++++++++++++
src/bin/pg_rewind/pg_rewind.c | 6 +++---
4 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/src/bin/pg_rewind/filemap.c b/src/bin/pg_rewind/filemap.c
index bd5c598e20..a0c8dbc1b6 100644
--- a/src/bin/pg_rewind/filemap.c
+++ b/src/bin/pg_rewind/filemap.c
@@ -795,7 +795,12 @@ decide_file_actions(void)
filehash_start_iterate(filehash, &it);
while ((entry = filehash_iterate(filehash, &it)) != NULL)
{
- entry->action = decide_file_action(entry);
+ /*
+ * Some entries (WAL segments) already have an action assigned
+ * (see findLastCheckpoint() function).
+ */
+ if (entry->action == FILE_ACTION_UNDECIDED)
+ entry->action = decide_file_action(entry);
}
/*
@@ -818,6 +823,18 @@ decide_file_actions(void)
return filemap;
}
+/*
+ * Prevent a given file deletion during rewind
+ */
+void
+preserve_file(char *filepath)
+{
+ file_entry_t *entry;
+
+ entry = insert_filehash_entry(filepath);
+ entry->action = FILE_ACTION_NONE;
+}
+
/*
* Helper function for filemap hash table.
diff --git a/src/bin/pg_rewind/filemap.h b/src/bin/pg_rewind/filemap.h
index 48f240dff1..47c7a7fd09 100644
--- a/src/bin/pg_rewind/filemap.h
+++ b/src/bin/pg_rewind/filemap.h
@@ -109,5 +109,6 @@ extern void process_target_wal_block_change(ForkNumber forknum,
extern filemap_t *decide_file_actions(void);
extern void calculate_totals(filemap_t *filemap);
extern void print_filemap(filemap_t *filemap);
+extern void preserve_file(char *filepath);
#endif /* FILEMAP_H */
diff --git a/src/bin/pg_rewind/parsexlog.c b/src/bin/pg_rewind/parsexlog.c
index 27782237d0..40c7073522 100644
--- a/src/bin/pg_rewind/parsexlog.c
+++ b/src/bin/pg_rewind/parsexlog.c
@@ -176,6 +176,10 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex,
char *errormsg;
XLogPageReadPrivate private;
+ /* Track WAL segments opened while searching a checkpoint */
+ XLogSegNo segno = 0;
+ TimeLineID tli = 0;
+
/*
* The given fork pointer points to the end of the last common record,
* which is not necessarily the beginning of the next record, if the
@@ -217,6 +221,24 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex,
LSN_FORMAT_ARGS(searchptr));
}
+ /* We are trying to detect if the new WAL file was opened */
+ if (xlogreader->seg.ws_tli != tli || xlogreader->seg.ws_segno != segno)
+ {
+ char xlogfname[MAXFNAMELEN];
+
+ tli = xlogreader->seg.ws_tli;
+ segno = xlogreader->seg.ws_segno;
+
+ snprintf(xlogfname, MAXPGPATH, XLOGDIR "/");
+ XLogFileName(xlogfname + strlen(xlogfname),
+ xlogreader->seg.ws_tli,
+ xlogreader->seg.ws_segno, WalSegSz);
+
+ /* Make sure pg_rewind doesn't remove this file, because it is
+ * required for postgres to start after rewind. */
+ preserve_file(xlogfname);
+ }
+
/*
* Check if it is a checkpoint record. This checkpoint record needs to
* be the latest checkpoint before WAL forked and not the checkpoint
diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c
index f7f3b8227f..bb52aa5466 100644
--- a/src/bin/pg_rewind/pg_rewind.c
+++ b/src/bin/pg_rewind/pg_rewind.c
@@ -446,14 +446,14 @@ main(int argc, char **argv)
exit(0);
}
+ /* Initialize the hash table to track the status of each file */
+ filehash_init();
+
findLastCheckpoint(datadir_target, divergerec, lastcommontliIndex,
&chkptrec, &chkpttli, &chkptredo, restore_command);
pg_log_info("rewinding from last common checkpoint at %X/%X on timeline %u",
LSN_FORMAT_ARGS(chkptrec), chkpttli);
- /* Initialize the hash table to track the status of each file */
- filehash_init();
-
/*
* Collect information about all files in the both data directories.
*/
--
2.34.1