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++;