Hi, On 2020-03-29 21:23:06 -0400, David Steele wrote: > On 3/29/20 9:07 PM, Andres Freund wrote: > > On 2020-03-29 20:42:35 -0400, Robert Haas wrote: > > > > What do you think of having the verification process also call > > > > pg_waldump to > > > > validate the WAL CRCs (shown upthread)? That looked helpful and simple. > > > > > > I don't love calls to external binaries, but I think the thing that > > > really bothers me is that pg_waldump is practically bound to terminate > > > with an error, because the last WAL segment will end with a partial > > > record. > > > > I don't think that's the case here. You should know the last required > > record, which should allow to specify the precise end for pg_waldump. If > > it errors out reading to that point, we'd be in trouble. > > Exactly. All WAL generated during the backup should read fine with > pg_waldump or there is a problem.
See the attached minimal prototype for what I am thinking of. This would not correctly handle the case where the timeline changes while taking a base backup. But I'm not sure that'd be all that serious a limitation for now? I'd personally not want to use a base backup that included a timeline switch... Greetings, Andres Freund
diff --git c/src/bin/pg_basebackup/pg_basebackup.c i/src/bin/pg_basebackup/pg_basebackup.c index c5d95958b29..b61492eba4c 100644 --- c/src/bin/pg_basebackup/pg_basebackup.c +++ i/src/bin/pg_basebackup/pg_basebackup.c @@ -2033,6 +2033,11 @@ BaseBackup(void) if (verbose) pg_log_info("base backup completed"); + + if (format == 'p') + pg_log_info("pg_waldump --just-parse -p \"%s\" -t %u -s %s -e %s", + basedir, starttli, + xlogstart, xlogend); } diff --git c/src/bin/pg_waldump/pg_waldump.c i/src/bin/pg_waldump/pg_waldump.c index 279acfa0440..63f4a9cba1f 100644 --- c/src/bin/pg_waldump/pg_waldump.c +++ i/src/bin/pg_waldump/pg_waldump.c @@ -40,6 +40,7 @@ typedef struct XLogDumpPrivate typedef struct XLogDumpConfig { /* display options */ + bool just_parse; bool bkp_details; int stop_after_records; int already_displayed_records; @@ -749,6 +750,7 @@ main(int argc, char **argv) char *errormsg; static struct option long_options[] = { + {"just-parse", no_argument, NULL, 'j'}, {"bkp-details", no_argument, NULL, 'b'}, {"end", required_argument, NULL, 'e'}, {"follow", no_argument, NULL, 'f'}, @@ -794,6 +796,7 @@ main(int argc, char **argv) private.endptr = InvalidXLogRecPtr; private.endptr_reached = false; + config.just_parse = false; config.bkp_details = false; config.stop_after_records = -1; config.already_displayed_records = 0; @@ -810,11 +813,14 @@ main(int argc, char **argv) goto bad_argument; } - while ((option = getopt_long(argc, argv, "be:fn:p:r:s:t:x:z", + while ((option = getopt_long(argc, argv, "be:fjn:p:r:s:t:x:z", long_options, &optindex)) != -1) { switch (option) { + case 'j': + config.just_parse = true; + break; case 'b': config.bkp_details = true; break; @@ -1076,10 +1082,13 @@ main(int argc, char **argv) continue; /* process the record */ - if (config.stats == true) - XLogDumpCountRecord(&config, &stats, xlogreader_state); - else - XLogDumpDisplayRecord(&config, xlogreader_state); + if (!config.just_parse) + { + if (config.stats == true) + XLogDumpCountRecord(&config, &stats, xlogreader_state); + else + XLogDumpDisplayRecord(&config, xlogreader_state); + } /* check whether we printed enough */ config.already_displayed_records++;