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

Commit8c6e3ad

Browse files
Basic Recovery Control functions for use in Hot Standby. Pause, Resume,
Status check functions only. Also, new recovery.conf parameter topause_at_recovery_target, default on.Simon Riggs, reviewed by Fujii Masao
1 parentf9f9d69 commit8c6e3ad

File tree

5 files changed

+230
-0
lines changed

5 files changed

+230
-0
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14173,6 +14173,64 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
1417314173
</tgroup>
1417414174
</table>
1417514175

14176+
<para>
14177+
The functions shown in <xref
14178+
linkend="functions-recovery-control-table"> control the progress of recovery.
14179+
These functions may be executed only during recovery.
14180+
</para>
14181+
14182+
<table id="functions-recovery-control-table">
14183+
<title>Recovery Control Functions</title>
14184+
<tgroup cols="3">
14185+
<thead>
14186+
<row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
14187+
</row>
14188+
</thead>
14189+
14190+
<tbody>
14191+
<row>
14192+
<entry>
14193+
<literal><function>pg_is_xlog_replay_paused()</function></literal>
14194+
</entry>
14195+
<entry><type>bool</type></entry>
14196+
<entry>True if recovery is paused.
14197+
</entry>
14198+
</row>
14199+
<row>
14200+
<entry>
14201+
<literal><function>pg_xlog_replay_pause()</function></literal>
14202+
</entry>
14203+
<entry><type>void</type></entry>
14204+
<entry>Pauses recovery immediately.
14205+
</entry>
14206+
</row>
14207+
<row>
14208+
<entry>
14209+
<literal><function>pg_xlog_replay_resume()</function></literal>
14210+
</entry>
14211+
<entry><type>void</type></entry>
14212+
<entry>Restarts recovery if it was paused.
14213+
</entry>
14214+
</row>
14215+
</tbody>
14216+
</tgroup>
14217+
</table>
14218+
14219+
<para>
14220+
While recovery is paused no further database changes are applied.
14221+
If in hot standby, all new queries will see the same consistent snapshot
14222+
of the database, and no further query conflicts will be generated until
14223+
recovery is resumed.
14224+
</para>
14225+
14226+
<para>
14227+
If streaming replication is disabled, the paused state may continue
14228+
indefinitely without problem. While streaming replication is in
14229+
progress WAL records will continue to be received, which will
14230+
eventually fill available disk space, depending upon the duration of
14231+
the pause, the rate of WAL generation and available disk space.
14232+
</para>
14233+
1417614234
<para>
1417714235
The functions shown in <xref linkend="functions-admin-dbsize"> calculate
1417814236
the disk space usage of database objects.

‎doc/src/sgml/recovery-config.sgml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,31 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
227227
</listitem>
228228
</varlistentry>
229229

230+
<varlistentry id="pause-at-recovery-target"
231+
xreflabel="pause_at_recovery_target">
232+
<term><varname>pause_at_recovery_target</varname>
233+
(<type>boolean</type>)
234+
</term>
235+
<indexterm>
236+
<primary><varname>pause_at_recovery_target</> recovery parameter</primary>
237+
</indexterm>
238+
<listitem>
239+
<para>
240+
Specifies whether recovery should pause when the recovery target
241+
is reached. The default is true, if a recovery target is set.
242+
This is intended to allow queries to be executed against the
243+
database to check if this recovery target is the most desirable
244+
point for recovery. The paused state can be resumed by using
245+
<function>pg_xlog_replay_resume()</> (See
246+
<xref linkend="functions-recovery-control-table">), which then
247+
causes recovery to end. If this recovery target is not the
248+
desired stopping point, then shutdown the server, change the
249+
recovery target settings to a later target and restart to
250+
continue recovery.
251+
</para>
252+
</listitem>
253+
</varlistentry>
254+
230255
</variablelist>
231256
</sect1>
232257

‎src/backend/access/transam/xlog.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ static char *recoveryEndCommand = NULL;
182182
staticchar*archiveCleanupCommand=NULL;
183183
staticRecoveryTargetTyperecoveryTarget=RECOVERY_TARGET_UNSET;
184184
staticboolrecoveryTargetInclusive= true;
185+
staticboolrecoveryPauseAtTarget= true;
185186
staticTransactionIdrecoveryTargetXid;
186187
staticTimestampTzrecoveryTargetTime;
187188

@@ -423,6 +424,8 @@ typedef struct XLogCtlData
423424
XLogRecPtrrecoveryLastRecPtr;
424425
/* timestamp of last COMMIT/ABORT record replayed (or being replayed) */
425426
TimestampTzrecoveryLastXTime;
427+
/* Are we requested to pause recovery? */
428+
boolrecoveryPause;
426429

427430
slock_tinfo_lck;/* locks shared variables shown above */
428431
}XLogCtlData;
@@ -570,6 +573,9 @@ static void readRecoveryCommandFile(void);
570573
staticvoidexitArchiveRecovery(TimeLineIDendTLI,
571574
uint32endLogId,uint32endLogSeg);
572575
staticboolrecoveryStopsHere(XLogRecord*record,bool*includeThis);
576+
staticvoidrecoveryPausesHere(void);
577+
staticboolRecoveryIsPaused(void);
578+
staticvoidSetRecoveryPause(boolrecoveryPause);
573579
staticvoidSetLatestXTime(TimestampTzxtime);
574580
staticTimestampTzGetLatestXTime(void);
575581
staticvoidCheckRequiredParameterValues(void);
@@ -5126,6 +5132,15 @@ readRecoveryCommandFile(void)
51265132
(errmsg("archive_cleanup_command = '%s'",
51275133
archiveCleanupCommand)));
51285134
}
5135+
elseif (strcmp(item->name,"pause_at_recovery_target")==0)
5136+
{
5137+
if (!parse_bool(item->value,&recoveryPauseAtTarget))
5138+
ereport(ERROR,
5139+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5140+
errmsg("parameter \"%s\" requires a Boolean value","pause_at_recovery_target")));
5141+
ereport(DEBUG2,
5142+
(errmsg("pause_at_recovery_target = '%s'",item->value)));
5143+
}
51295144
elseif (strcmp(item->name,"recovery_target_timeline")==0)
51305145
{
51315146
rtliGiven= true;
@@ -5508,6 +5523,110 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
55085523
returnstopsHere;
55095524
}
55105525

5526+
/*
5527+
* Recheck shared recoveryPause by polling.
5528+
*
5529+
* XXX Can also be done with shared latch.
5530+
*/
5531+
staticvoid
5532+
recoveryPausesHere(void)
5533+
{
5534+
while (RecoveryIsPaused());
5535+
{
5536+
pg_usleep(1000000L);/* 1000 ms */
5537+
HandleStartupProcInterrupts();
5538+
};
5539+
}
5540+
5541+
staticbool
5542+
RecoveryIsPaused(void)
5543+
{
5544+
/* use volatile pointer to prevent code rearrangement */
5545+
volatileXLogCtlData*xlogctl=XLogCtl;
5546+
boolrecoveryPause;
5547+
5548+
SpinLockAcquire(&xlogctl->info_lck);
5549+
recoveryPause=xlogctl->recoveryPause;
5550+
SpinLockRelease(&xlogctl->info_lck);
5551+
5552+
returnrecoveryPause;
5553+
}
5554+
5555+
staticvoid
5556+
SetRecoveryPause(boolrecoveryPause)
5557+
{
5558+
/* use volatile pointer to prevent code rearrangement */
5559+
volatileXLogCtlData*xlogctl=XLogCtl;
5560+
5561+
SpinLockAcquire(&xlogctl->info_lck);
5562+
xlogctl->recoveryPause=recoveryPause;
5563+
SpinLockRelease(&xlogctl->info_lck);
5564+
}
5565+
5566+
/*
5567+
* pg_xlog_replay_pause - pause recovery now
5568+
*/
5569+
Datum
5570+
pg_xlog_replay_pause(PG_FUNCTION_ARGS)
5571+
{
5572+
if (!superuser())
5573+
ereport(ERROR,
5574+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
5575+
(errmsg("must be superuser to control recovery"))));
5576+
5577+
if (!RecoveryInProgress())
5578+
ereport(ERROR,
5579+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
5580+
errmsg("recovery is not in progress"),
5581+
errhint("Recovery control functions can only be executed during recovery.")));
5582+
5583+
SetRecoveryPause(true);
5584+
5585+
PG_RETURN_VOID();
5586+
}
5587+
5588+
/*
5589+
* pg_xlog_replay_resume - resume recovery now
5590+
*/
5591+
Datum
5592+
pg_xlog_replay_resume(PG_FUNCTION_ARGS)
5593+
{
5594+
if (!superuser())
5595+
ereport(ERROR,
5596+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
5597+
(errmsg("must be superuser to control recovery"))));
5598+
5599+
if (!RecoveryInProgress())
5600+
ereport(ERROR,
5601+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
5602+
errmsg("recovery is not in progress"),
5603+
errhint("Recovery control functions can only be executed during recovery.")));
5604+
5605+
SetRecoveryPause(false);
5606+
5607+
PG_RETURN_VOID();
5608+
}
5609+
5610+
/*
5611+
* pg_is_xlog_replay_paused
5612+
*/
5613+
Datum
5614+
pg_is_xlog_replay_paused(PG_FUNCTION_ARGS)
5615+
{
5616+
if (!superuser())
5617+
ereport(ERROR,
5618+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
5619+
(errmsg("must be superuser to control recovery"))));
5620+
5621+
if (!RecoveryInProgress())
5622+
ereport(ERROR,
5623+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
5624+
errmsg("recovery is not in progress"),
5625+
errhint("Recovery control functions can only be executed during recovery.")));
5626+
5627+
PG_RETURN_BOOL(RecoveryIsPaused());
5628+
}
5629+
55115630
/*
55125631
* Save timestamp of latest processed commit/abort record.
55135632
*
@@ -6074,6 +6193,13 @@ StartupXLOG(void)
60746193
StandbyRecoverPreparedTransactions(false);
60756194
}
60766195
}
6196+
else
6197+
{
6198+
/*
6199+
* Must not pause unless we are going to enter Hot Standby.
6200+
*/
6201+
recoveryPauseAtTarget= false;
6202+
}
60776203

60786204
/* Initialize resource managers */
60796205
for (rmid=0;rmid <=RM_MAX_ID;rmid++)
@@ -6098,6 +6224,7 @@ StartupXLOG(void)
60986224
xlogctl->replayEndRecPtr=ReadRecPtr;
60996225
xlogctl->recoveryLastRecPtr=ReadRecPtr;
61006226
xlogctl->recoveryLastXTime=0;
6227+
xlogctl->recoveryPause= false;
61016228
SpinLockRelease(&xlogctl->info_lck);
61026229

61036230
/* Also ensure XLogReceiptTime has a sane value */
@@ -6146,6 +6273,7 @@ StartupXLOG(void)
61466273
{
61476274
boolrecoveryContinue= true;
61486275
boolrecoveryApply= true;
6276+
boolrecoveryPause= false;
61496277
ErrorContextCallbackerrcontext;
61506278
TimestampTzxtime;
61516279

@@ -6192,6 +6320,11 @@ StartupXLOG(void)
61926320
*/
61936321
if (recoveryStopsHere(record,&recoveryApply))
61946322
{
6323+
if (recoveryPauseAtTarget)
6324+
{
6325+
SetRecoveryPause(true);
6326+
recoveryPausesHere();
6327+
}
61956328
reachedStopPoint= true;/* see below */
61966329
recoveryContinue= false;
61976330
if (!recoveryApply)
@@ -6218,8 +6351,12 @@ StartupXLOG(void)
62186351
*/
62196352
SpinLockAcquire(&xlogctl->info_lck);
62206353
xlogctl->replayEndRecPtr=EndRecPtr;
6354+
recoveryPause=xlogctl->recoveryPause;
62216355
SpinLockRelease(&xlogctl->info_lck);
62226356

6357+
if (recoveryPause)
6358+
recoveryPausesHere();
6359+
62236360
/*
62246361
* If we are attempting to enter Hot Standby mode, process
62256362
* XIDs we see

‎src/include/access/xlog_internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,5 +275,8 @@ extern Datum pg_last_xact_replay_timestamp(PG_FUNCTION_ARGS);
275275
externDatumpg_xlogfile_name_offset(PG_FUNCTION_ARGS);
276276
externDatumpg_xlogfile_name(PG_FUNCTION_ARGS);
277277
externDatumpg_is_in_recovery(PG_FUNCTION_ARGS);
278+
externDatumpg_xlog_replay_pause(PG_FUNCTION_ARGS);
279+
externDatumpg_xlog_replay_resume(PG_FUNCTION_ARGS);
280+
externDatumpg_is_xlog_replay_paused(PG_FUNCTION_ARGS);
278281

279282
#endif/* XLOG_INTERNAL_H */

‎src/include/catalog/pg_proc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3416,6 +3416,13 @@ DESCR("last xlog replay location");
34163416
DATA(insertOID=3830 (pg_last_xact_replay_timestampPGNSPPGUID12100ffftfv001184""_null__null__null__null_pg_last_xact_replay_timestamp_null__null__null_ ));
34173417
DESCR("timestamp of last replay xact");
34183418

3419+
DATA(insertOID=3071 (pg_xlog_replay_pausePGNSPPGUID12100ffftfv002278""_null__null__null__null_pg_xlog_replay_pause_null__null__null_ ));
3420+
DESCR("pauses xlog replay");
3421+
DATA(insertOID=3072 (pg_xlog_replay_resumePGNSPPGUID12100ffftfv002278""_null__null__null__null_pg_xlog_replay_resume_null__null__null_ ));
3422+
DESCR("resumes xlog replay, if it was paused");
3423+
DATA(insertOID=3073 (pg_is_xlog_replay_pausedPGNSPPGUID12100ffftfv0016""_null__null__null__null_pg_is_xlog_replay_paused_null__null__null_ ));
3424+
DESCR("true if xlog replay is paused");
3425+
34193426
DATA(insertOID=2621 (pg_reload_confPGNSPPGUID12100ffftfv0016""_null__null__null__null_pg_reload_conf_null__null__null_ ));
34203427
DESCR("reload configuration files");
34213428
DATA(insertOID=2622 (pg_rotate_logfilePGNSPPGUID12100ffftfv0016""_null__null__null__null_pg_rotate_logfile_null__null__null_ ));

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp