From 71e74a2f587ab8847e99b431b40d6acf62144128 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Wed, 2 Oct 2002 21:30:13 +0000 Subject: [PATCH] Re-enable pg_resetxlog to accept -l values in hexadecimal (it used to be able to do that, but the ability seems to have got lost in the shuffle). Add a -o nextOID switch for completeness. Improve the documentation to explain how and why to use these switches. --- doc/src/sgml/ref/pg_resetxlog.sgml | 51 ++++++++++++++++----- src/bin/pg_resetxlog/pg_resetxlog.c | 71 ++++++++++++++++++++++------- 2 files changed, 94 insertions(+), 28 deletions(-) diff --git a/doc/src/sgml/ref/pg_resetxlog.sgml b/doc/src/sgml/ref/pg_resetxlog.sgml index 00b24fe0168..61fce46a17d 100644 --- a/doc/src/sgml/ref/pg_resetxlog.sgml +++ b/doc/src/sgml/ref/pg_resetxlog.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_resetxlog.sgml,v 1.5 2002/08/29 22:19:03 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_resetxlog.sgml,v 1.6 2002/10/02 21:30:13 tgl Exp $ PostgreSQL documentation --> @@ -12,7 +12,7 @@ PostgreSQL documentation <refnamediv> <refname>pg_resetxlog</refname> - <refpurpose>reset write-ahead log file and optionally the pg_control file</refpurpose> + <refpurpose>reset write-ahead log and pg_control contents</refpurpose> </refnamediv> <refsynopsisdiv> @@ -20,6 +20,7 @@ PostgreSQL documentation <command>pg_resetxlog</command> <arg> -f </arg> <arg> -n </arg> + <arg> -o <replaceable class="parameter">oid</replaceable> </arg> <arg> -x <replaceable class="parameter">xid</replaceable> </arg> <arg> -l <replaceable class="parameter">fileid</replaceable>,<replaceable class="parameter">seg</replaceable> </arg> <arg choice="plain"><replaceable>datadir</replaceable></arg> @@ -29,8 +30,9 @@ PostgreSQL documentation <refsect1 id="R1-APP-PGRESETXLOG-1"> <title>Description</title> <para> - <command>pg_resetxlog</command> clears the write-ahead log file and - optionally the <filename>pg_control</> file. This function is sometimes + <command>pg_resetxlog</command> clears the write-ahead log and + optionally resets some fields in the <filename>pg_control</> file. This + function is sometimes needed if these files have become corrupted. It should be used only as a last resort, when the server will not start due to such corruption. @@ -55,14 +57,45 @@ PostgreSQL documentation <para> If <command>pg_resetxlog</command> complains that it cannot determine valid data for <filename>pg_control</>, you can force it to proceed anyway - by specifying the <literal>-f</> (force) switch. In this case plausible values - will be substituted for the missing data. If <literal>-f</> is used then + by specifying the <literal>-f</> (force) switch. In this case plausible + values will be substituted for the missing data. Most of the fields can be + expected to match, but manual assistance may be needed for the next OID, + next transaction ID, WAL starting address, and database locale fields. + The first three of these can be set using the switches discussed below. + <command>pg_resetxlog</command>'s own environment is the source for its + guess at the locale fields; take care that <envar>LANG</> and so forth + match the environment that <application>initdb</> was run in. + If you are not able to determine correct values for all these fields, + <literal>-f</> can still be used, but the recovered database must be treated with even more suspicion than usual --- an immediate dump and reload is imperative. <emphasis>Do not</> execute any data-modifying operations in the database before you dump, as any such action is likely to make the corruption worse. </para> + <para> + The <literal>-o</>, <literal>-x</>, and <literal>-l</> switches allow + the next OID, next transaction ID, and WAL starting address values to + be set manually. These are only needed when + <command>pg_resetxlog</command> is unable to determine appropriate values + by reading <filename>pg_control</>. A safe value for the + next transaction ID may be determined by looking for the largest + file name in <envar>$PGDATA</><filename>/pg_clog</>, adding one, + and then multiplying by 1048576. Note that the file names are in + hexadecimal. It is usually easiest to specify the switch value in + hexadecimal too. For example, if <filename>0011</> is the largest entry + in <filename>pg_clog</>, <literal>-x 0x1200000</> will work (five trailing + zeroes provide the proper multiplier). + The WAL starting address should be + larger than any file number currently existing in + <envar>$PGDATA</><filename>/pg_xlog</>. These also are in hex, and + have two parts. For example, if <filename>000000FF0000003A</> is the + largest entry in <filename>pg_xlog</>, <literal>-l 0xFF,0x3B</> will work. + There is no comparably easy way to determine a next OID that's beyond + the largest one in the database, but fortunately it is not critical to + get the next-OID setting right. + </para> + <para> The <literal>-n</> (no operation) switch instructs <command>pg_resetxlog</command> to print the values reconstructed from @@ -70,12 +103,6 @@ PostgreSQL documentation This is mainly a debugging tool, but may be useful as a sanity check before allowing <command>pg_resetxlog</command> to proceed for real. </para> - - <para> - The <literal>-x</> and <literal>-l</> switches are intended for use by - <application>pg_upgrade</>. In most cases they should not be used in - manual recovery operations. - </para> </refsect1> <refsect1> diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c index 56621cd5569..81fb79b3a39 100644 --- a/src/bin/pg_resetxlog/pg_resetxlog.c +++ b/src/bin/pg_resetxlog/pg_resetxlog.c @@ -23,7 +23,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.6 2002/10/02 19:45:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.7 2002/10/02 21:30:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -90,8 +90,11 @@ main(int argc, char *argv[]) bool force = false; bool noupdate = false; TransactionId set_xid = 0; + Oid set_oid = 0; uint32 minXlogId = 0, minXlogSeg = 0; + char *endptr; + char *endptr2; char *DataDir; int fd; char path[MAXPGPATH]; @@ -122,7 +125,7 @@ main(int argc, char *argv[]) } - while ((c = getopt(argc, argv, "fl:nx:")) != -1) + while ((c = getopt(argc, argv, "fl:no:x:")) != -1) { switch (c) { @@ -135,7 +138,13 @@ main(int argc, char *argv[]) break; case 'x': - set_xid = strtoul(optarg, NULL, 0); + set_xid = strtoul(optarg, &endptr, 0); + if (endptr == optarg || *endptr != '\0') + { + fprintf(stderr, _("%s: invalid argument for -x option\n"), progname); + fprintf(stderr, _("Try '%s --help' for more information.\n"), progname); + exit(1); + } if (set_xid == 0) { fprintf(stderr, _("%s: transaction ID (-x) must not be 0\n"), progname); @@ -143,8 +152,31 @@ main(int argc, char *argv[]) } break; + case 'o': + set_oid = strtoul(optarg, &endptr, 0); + if (endptr == optarg || *endptr != '\0') + { + fprintf(stderr, _("%s: invalid argument for -o option\n"), progname); + fprintf(stderr, _("Try '%s --help' for more information.\n"), progname); + exit(1); + } + if (set_oid == 0) + { + fprintf(stderr, _("%s: OID (-o) must not be 0\n"), progname); + exit(1); + } + break; + case 'l': - if (sscanf(optarg, "%u,%u", &minXlogId, &minXlogSeg) != 2) + minXlogId = strtoul(optarg, &endptr, 0); + if (endptr == optarg || *endptr != ',') + { + fprintf(stderr, _("%s: invalid argument for -l option\n"), progname); + fprintf(stderr, _("Try '%s --help' for more information.\n"), progname); + exit(1); + } + minXlogSeg = strtoul(endptr+1, &endptr2, 0); + if (endptr2 == endptr+1 || *endptr2 != '\0') { fprintf(stderr, _("%s: invalid argument for -l option\n"), progname); fprintf(stderr, _("Try '%s --help' for more information.\n"), progname); @@ -198,6 +230,24 @@ main(int argc, char *argv[]) if (!ReadControlFile()) GuessControlValues(); + /* + * Adjust fields if required by switches. (Do this now so that + * printout, if any, includes these values.) + */ + if (set_xid != 0) + ControlFile.checkPointCopy.nextXid = set_xid; + + if (set_oid != 0) + ControlFile.checkPointCopy.nextOid = set_oid; + + if (minXlogId > ControlFile.logId || + (minXlogId == ControlFile.logId && + minXlogSeg > ControlFile.logSeg)) + { + ControlFile.logId = minXlogId; + ControlFile.logSeg = minXlogSeg; + } + /* * If we had to guess anything, and -f was not given, just print the * guessed values and exit. Also print if -n is given. @@ -227,19 +277,7 @@ main(int argc, char *argv[]) /* * Else, do the dirty deed. - * - * First adjust fields if required by switches. */ - if (set_xid != 0) - ControlFile.checkPointCopy.nextXid = set_xid; - - if (minXlogId > ControlFile.logId || - (minXlogId == ControlFile.logId && minXlogSeg > ControlFile.logSeg)) - { - ControlFile.logId = minXlogId; - ControlFile.logSeg = minXlogSeg; - } - RewriteControlFile(); KillExistingXLOG(); WriteEmptyXLOG(); @@ -659,6 +697,7 @@ usage(void) printf(_(" -f force update to be done\n")); printf(_(" -l FILEID,SEG force minimum WAL starting location for new transaction log\n")); printf(_(" -n no update, just show extracted control values (for testing)\n")); + printf(_(" -o OID set next OID\n")); printf(_(" -x XID set next transaction ID\n")); printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n")); } -- GitLab