Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5adafaf

Browse files
committed
Have pg_rewind run crash recovery before rewinding
If we don't do this, the rewind fails if the server wasn't cleanly shutdown, which seems unhelpful serving no purpose.Also provide a new option --no-ensure-shutdown to suppress thisbehavior, for alleged advanced usage that prefers to avoid the crashrecovery.Authors: Paul Guo, Jimmy Yih, Ashwin AgrawalReviewed-by: Álvaro HerreraDiscussion:https://postgr.es/m/CAEET0ZEffUkXc48pg2iqARQgGRYDiiVxDu+yYek_bTwJF+q=Uw@mail.gmail.com
1 parentc967e13 commit5adafaf

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

‎doc/src/sgml/ref/pg_rewind.sgml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,21 @@ PostgreSQL documentation
165165
</listitem>
166166
</varlistentry>
167167

168+
<varlistentry>
169+
<term><option>--no-ensure-shutdown</option></term>
170+
<listitem>
171+
<para>
172+
<application>pg_rewind</application> verifies that the target server
173+
is cleanly shutdown before rewinding; by default, if it isn't, it
174+
starts the server in single-user mode to complete crash recovery.
175+
By passing this option, <application>pg_rewind</application> skips
176+
this and errors out immediately if the server is not cleanly shut
177+
down. Users are expected to handle the situation themselves in that
178+
case.
179+
</para>
180+
</listitem>
181+
</varlistentry>
182+
168183
<varlistentry>
169184
<term><option>-n</option></term>
170185
<term><option>--dry-run</option></term>

‎src/bin/pg_rewind/pg_rewind.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ static void digestControlFile(ControlFileData *ControlFile, char *source,
4040
staticvoidsyncTargetDirectory(void);
4141
staticvoidsanityChecks(void);
4242
staticvoidfindCommonAncestorTimeline(XLogRecPtr*recptr,int*tliIndex);
43+
staticvoidensureCleanShutdown(constchar*argv0);
4344

4445
staticControlFileDataControlFile_target;
4546
staticControlFileDataControlFile_source;
@@ -79,6 +80,7 @@ usage(const char *progname)
7980
printf(_(" -N, --no-sync do not wait for changes to be written\n"
8081
" safely to disk\n"));
8182
printf(_(" -P, --progress write progress messages\n"));
83+
printf(_(" --no-ensure-shutdown do not automatically fix unclean shutdown\n"));
8284
printf(_(" --debug write a lot of debug messages\n"));
8385
printf(_(" -V, --version output version information, then exit\n"));
8486
printf(_(" -?, --help show this help, then exit\n"));
@@ -94,6 +96,7 @@ main(int argc, char **argv)
9496
{"target-pgdata",required_argument,NULL,'D'},
9597
{"source-pgdata",required_argument,NULL,1},
9698
{"source-server",required_argument,NULL,2},
99+
{"no-ensure-shutdown",no_argument,NULL,44},
97100
{"version",no_argument,NULL,'V'},
98101
{"dry-run",no_argument,NULL,'n'},
99102
{"no-sync",no_argument,NULL,'N'},
@@ -110,6 +113,7 @@ main(int argc, char **argv)
110113
XLogRecPtrchkptredo;
111114
size_tsize;
112115
char*buffer;
116+
boolno_ensure_shutdown= false;
113117
boolrewind_needed;
114118
XLogRecPtrendrec;
115119
TimeLineIDendtli;
@@ -169,6 +173,9 @@ main(int argc, char **argv)
169173
case2:/* --source-server */
170174
connstr_source=pg_strdup(optarg);
171175
break;
176+
case4:
177+
no_ensure_shutdown= true;
178+
break;
172179
}
173180
}
174181

@@ -241,6 +248,24 @@ main(int argc, char **argv)
241248
digestControlFile(&ControlFile_target,buffer,size);
242249
pg_free(buffer);
243250

251+
/*
252+
* If the target instance was not cleanly shut down, run a single-user
253+
* postgres session really quickly and reload the control file to get the
254+
* new state. Note if no_ensure_shutdown is specified, pg_rewind won't do
255+
* that automatically. That means users need to do themselves in advance,
256+
* else pg_rewind will soon quit, see sanityChecks().
257+
*/
258+
if (!no_ensure_shutdown&&
259+
ControlFile_target.state!=DB_SHUTDOWNED&&
260+
ControlFile_target.state!=DB_SHUTDOWNED_IN_RECOVERY)
261+
{
262+
ensureCleanShutdown(argv[0]);
263+
264+
buffer=slurpFile(datadir_target,"global/pg_control",&size);
265+
digestControlFile(&ControlFile_target,buffer,size);
266+
pg_free(buffer);
267+
}
268+
244269
buffer=fetchFile("global/pg_control",&size);
245270
digestControlFile(&ControlFile_source,buffer,size);
246271
pg_free(buffer);
@@ -748,3 +773,58 @@ syncTargetDirectory(void)
748773

749774
fsync_pgdata(datadir_target,PG_VERSION_NUM);
750775
}
776+
777+
/*
778+
* Ensure clean shutdown of target instance by launching single-user mode
779+
* postgres to do crash recovery.
780+
*/
781+
staticvoid
782+
ensureCleanShutdown(constchar*argv0)
783+
{
784+
intret;
785+
#defineMAXCMDLEN (2 * MAXPGPATH)
786+
charexec_path[MAXPGPATH];
787+
charcmd[MAXCMDLEN];
788+
789+
/* locate postgres binary */
790+
if ((ret=find_other_exec(argv0,"postgres",
791+
PG_BACKEND_VERSIONSTR,
792+
exec_path))<0)
793+
{
794+
charfull_path[MAXPGPATH];
795+
796+
if (find_my_exec(argv0,full_path)<0)
797+
strlcpy(full_path,progname,sizeof(full_path));
798+
799+
if (ret==-1)
800+
pg_fatal("The program \"%s\" is needed by %s but was\n"
801+
"not found in the same directory as \"%s\".\n"
802+
"Check your installation.",
803+
"postgres",progname,full_path);
804+
else
805+
pg_fatal("The program \"%s\" was found by \"%s\" but was\n"
806+
"not the same version as %s.\n"
807+
"Check your installation.",
808+
"postgres",full_path,progname);
809+
}
810+
811+
pg_log_info("executing \"%s\" for target server to complete crash recovery",
812+
exec_path);
813+
814+
/*
815+
* Skip processing if requested, but only after ensuring presence of
816+
* postgres.
817+
*/
818+
if (dry_run)
819+
return;
820+
821+
/* finally run postgres in single-user mode */
822+
snprintf(cmd,MAXCMDLEN,"\"%s\" --single -D \"%s\" template1 < \"%s\"",
823+
exec_path,datadir_target,DEVNULL);
824+
825+
if (system(cmd)!=0)
826+
{
827+
pg_log_error("postgres single-user mode of target instance failed");
828+
pg_fatal("Command was: %s",cmd);
829+
}
830+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp