summaryrefslogtreecommitdiff
path: root/src/bin/pg_rewind/parsexlog.c
diff options
context:
space:
mode:
authorÁlvaro Herrera2024-11-15 11:53:12 +0000
committerÁlvaro Herrera2024-11-15 11:53:12 +0000
commit90bcc7c2db1d346e1153748e627c2f922b67eae7 (patch)
treeaac69ee331e9278a7c95976be781c0df6f0c4557 /src/bin/pg_rewind/parsexlog.c
parentd31bbfb6590e586f731345960311861d5eb4c23f (diff)
Avoid deleting critical WAL segments during pg_rewind
Previously, in unlucky cases, it was possible for pg_rewind to remove certain WAL segments from the rewound demoted primary. In particular this happens if those files have been marked for archival (i.e., their .ready files were created) but not yet archived; the newly promoted node no longer has such files because of them having been recycled, but they are likely critical for recovery in the demoted node. If pg_rewind removes them, recovery is not possible anymore. Fix this by maintaining a hash table of files in this situation in the scan that looks for a checkpoint, which the decide_file_actions phase can consult so that it knows to preserve them. Backpatch to 14. The problem also exists in 13, but that branch was not blessed with commit eb00f1d4bf96, so this patch is difficult to apply there. Users of older releases will just have to continue to be extra careful when rewinding. Co-authored-by: Полина Бунгина (Polina Bungina) <[email protected]> Co-authored-by: Alexander Kukushkin <[email protected]> Reviewed-by: Kyotaro Horiguchi <[email protected]> Reviewed-by: Atsushi Torikoshi <[email protected]> Discussion: https://postgr.es/m/CAAtGL4AhzmBRsEsaDdz7065T+k+BscNadfTqP1NcPmsqwA5HBw@mail.gmail.com
Diffstat (limited to 'src/bin/pg_rewind/parsexlog.c')
-rw-r--r--src/bin/pg_rewind/parsexlog.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/src/bin/pg_rewind/parsexlog.c b/src/bin/pg_rewind/parsexlog.c
index 22f7351fdcd..242326c97a7 100644
--- a/src/bin/pg_rewind/parsexlog.c
+++ b/src/bin/pg_rewind/parsexlog.c
@@ -175,6 +175,8 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex,
XLogReaderState *xlogreader;
char *errormsg;
XLogPageReadPrivate private;
+ XLogSegNo current_segno = 0;
+ TimeLineID current_tli = 0;
/*
* The given fork pointer points to the end of the last common record,
@@ -217,6 +219,25 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex,
LSN_FORMAT_ARGS(searchptr));
}
+ /* Detect if a new WAL file has been opened */
+ if (xlogreader->seg.ws_tli != current_tli ||
+ xlogreader->seg.ws_segno != current_segno)
+ {
+ char xlogfname[MAXFNAMELEN];
+
+ snprintf(xlogfname, MAXFNAMELEN, XLOGDIR "/");
+
+ /* update curent values */
+ current_tli = xlogreader->seg.ws_tli;
+ current_segno = xlogreader->seg.ws_segno;
+
+ XLogFileName(xlogfname + sizeof(XLOGDIR),
+ current_tli, current_segno, WalSegSz);
+
+ /* Track this filename as one to not remove */
+ keepwal_add_entry(xlogfname);
+ }
+
/*
* Check if it is a checkpoint record. This checkpoint record needs to
* be the latest checkpoint before WAL forked and not the checkpoint