#author("2019-04-20T12:52:21+00:00","default:haikikyou","haikikyou")
[[PostgreSQL/解析]]

* アーカイブ [#c2eb60f9]

データベースをPITR(ポイントタイムリカバリ)で任意の地点に復旧させるのにデータベースの先行書き込みログ(WAL)が必要となる。アーカイブ設定を行なうことで、PostgreSQLの機能により、walディレクトリのWALを定期的にバックアップ領域に保存できるようになる。PITRでは、ファイルシステムレベルのバックアップ(ex: pg_basebackup)とWALバックアップを用いて復旧させる。

* Archiver [#uad4ce3c]
&ref(./archiver.png);
-  WALアーカイブを実行しているのは、Archiverプロセスである。
- Archiverプロセスは、起動後はメインループ内でアーカイブコピーを繰り返し行なう。
- メインループはLatchでwaitし、およそ&code(){PGARCH_AUTOWAKE_INTERVAL};(60秒)ごとにwaitから戻る。Latchのタイムアウトは以下で計算される。last_copy_timeは最後にアーカイブされた時間、curtimeはLatchでwaitする前に取得される時間。よってアーカイブされない時間がPGARCH_AUTOWAKE_INTERVAL秒を経過するとSetLatchでLatchが外れ(TIMEOUT)、&code(){wakened = true};となる。
 PGARCH_AUTOWAKE_INTERVAL - (curtime - last_copy_time)
&label(warn){参考}; [[backend/postmaster/pgarch.c#pgarch_MainLoop()>https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/postmaster/pgarch.c;h=dc2739bf36db4bbc318a82dba42f8e34d58b68ef;hb=refs/heads/REL_10_STABLE#l367]]
- archive_statusディレクトリから、.readyがサフィックスであるファイルを探す。~
historyファイルが存在する場合はそれが優先され、複数のhistoryファイルが存在する場合は、最も古いhistoryファイルが優先される。


** アーカイブコピーの契機 [#refb53f8]

- Latchでタイムアウト秒経過する
- シグナル(SIGUSR1)を受けとる(SetLatchでLatchが外れる)
-- Postmasterはsigusr1_handlerでPMSIGNAL_WAKEN_ARCHIVERシグナルであることを確認し、ArchiverにSIGUSR1を送る。Archiverは、シグナルハンドラでwakened = trueにフラグ更新。Latchが外れアーカイブコピーを実行する。

** WALアーカイブ処理の流れ [#mf17460f]

- archive_statusディレクトリに.readyファイルがあるかチェックする
- archive_commandがセットされているか確認する。コマンドがセットされていない場合はアーカイブを実行しない。WARNINGが出る。
-- archive_mode enabled, yet archive_command is not set
-  walディレクトリから、.readyで示されるwalログファイルを探す。該当するファイルが存在しない場合、孤児となった.readyを消す。消すのに失敗した場合、1秒のインターバルで&code(){NUM_ORPHAN_CLEANUP_RETRIES};(3回)失敗するまで試行する。
- WALアーカイブ
-- WALアーカイブは、&code(){archive_command};で指定されているコマンドを&code(){system};関数でキックすることで行われる。
-- WALアーカイブに成功した場合は、.readyを.doneにする。
- 統計情報コレクタに、Archiverの統計情報を送る(pg_stat_archiverビュー)。
#geshi(sql){{{
-- Archiverの統計情報確認
select * from pg_stat_archiver
-[ RECORD 1 ]------+------------------------------
archived_count     | 1
last_archived_wal  | 000000010000000000000001
last_archived_time | 2019-03-20 21:44:59.918306+09
failed_count       | 0
last_failed_wal    | 
last_failed_time   | 
stats_reset        | 2019-03-20 21:42:17.409563+09

-- リセット
select pg_stat_reset_shared('archiver')
-[ RECORD 1 ]--------+-
pg_stat_reset_shared | 

-- リセットした後
select * from pg_stat_archiver
-[ RECORD 1 ]------+------------------------------
archived_count     | 0
last_archived_wal  | 
last_archived_time | 
failed_count       | 0
last_failed_wal    | 
last_failed_time   | 
stats_reset        | 2019-04-20 21:46:54.795811+09
}}}

&label(warn){参考}; 

- [[backend/postmaster/pgarch.c>https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/postmaster/pgarch.c;h=dc2739bf36db4bbc318a82dba42f8e34d58b68ef;hb=refs/heads/REL_10_STABLE]] - &size(11){&color(gray){https://git.postgresql.org/gitweb/?p=postgresql.git;a=shortlog;h=refs/heads/REL_10_STABLE};};
- [[pg_stat_archiverビュー>https://www.postgresql.jp/document/10/html/monitoring-stats.html#PG-STAT-ARCHIVER-VIEW]] - &size(11){&color(gray){on https://www.postgresql.jp/document/10/html/monitoring-stats.html#PG-STAT-ARCHIVER-VIEW};};
* pg_switch_wal() [#o8c5fda8]

&code(){pg_switch_wal};関数は、強制的にWALセグメントの切り替えを行なう。~
&code(){pg_waldump};でWALの内部を解析すると、XLOG rmgrのinfo値で&code(){XLOG_SWITCH};という種別のWALが書き込まれる。

#geshi{{{
rmgr: XLOG        len (rec/tot):     24/    24, tx:          0, lsn: 0/18000060, prev 0/18000028, desc: SWITCH 
}}}

連続実行してもWAL位置に変更がなければスイッチはされない。その場合は、同じSWITCHポイントが戻る。

#geshi(sql){{{
# select pg_switch_wal();を実行している

postgres=# \watch 1
土  4/20 17:38:51 2019 (every 1s)

 pg_switch_wal 
---------------
 0/45000078
(1 row)

土  4/20 17:38:55 2019 (every 1s)

 pg_switch_wal 
---------------
 0/46000078
(1 row)

土  4/20 17:38:56 2019 (every 1s)

 pg_switch_wal 
---------------
 0/47000000
(1 row)

土  4/20 17:38:57 2019 (every 1s)

 pg_switch_wal 
---------------
 0/47000000
(1 row)

土  4/20 17:38:58 2019 (every 1s)

 pg_switch_wal 
---------------
 0/47000000
(1 row)

土  4/20 17:38:59 2019 (every 1s)

 pg_switch_wal 
---------------
 0/47000000
(1 row)

土  4/20 17:39:00 2019 (every 1s)

 pg_switch_wal 
---------------
 0/47000000
(1 row)

}}}
&label(warn){参考};
- [[backend/access/transam/xlog.c#XLogFlush()>https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/access/transam/xlog.c;h=a93017feecffae7a7ff65d40b78a89556d55eb51;hb=refs/heads/REL_10_STABLE#l2800]] - &size(11){&color(gray){https://git.postgresql.org/gitweb/?p=postgresql.git;a=shortlog;h=refs/heads/REL_10_STABLE};};
- [[9.26.3. バックアップ制御関数>https://www.postgresql.jp/document/10/html/functions-admin.html]] - https://www.postgresql.jp/document/10/html/functions-admin.html

SWITCH切り替え時、WALセグメントはセグメントサイズまで消費される。

&label(blockquote){引用}; [[backend/access/transam/xlog.c#CopyXLogRecordToWAL()>https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/access/transam/xlog.c;h=a93017feecffae7a7ff65d40b78a89556d55eb51;hb=refs/heads/REL_10_STABLE#l1541]]
#geshi(c){{{
// backend/access/transam/xlog.c#CopyXLogRecordToWAL()
	/*
	 * If this was an xlog-switch, it's not enough to write the switch record,
	 * we also have to consume all the remaining space in the WAL segment.  We
	 * have already reserved that space, but we need to actually fill it.
	 */
	if (isLogSwitch && XLogSegmentOffset(CurrPos, wal_segment_size) != 0)
	{
		/* An xlog-switch record doesn't contain any data besides the header */
		Assert(write_len == SizeOfXLogRecord);

		/* Assert that we did reserve the right amount of space */
		Assert(XLogSegmentOffset(EndPos, wal_segment_size) == 0);

		/* Use up all the remaining space on the current page */
		CurrPos += freespace;

		/*
		 * Cause all remaining pages in the segment to be flushed, leaving the
		 * XLog position where it should be, at the start of the next segment.
		 * We do this one page at a time, to make sure we don't deadlock
		 * against ourselves if wal_buffers < wal_segment_size.
		 */
		while (CurrPos < EndPos)
		{
			/*
			 * The minimal action to flush the page would be to call
			 * WALInsertLockUpdateInsertingAt(CurrPos) followed by
			 * AdvanceXLInsertBuffer(...).  The page would be left initialized
			 * mostly to zeros, except for the page header (always the short
			 * variant, as this is never a segment's first page).
			 *
			 * The large vistas of zeros are good for compressibility, but the
			 * headers interrupting them every XLOG_BLCKSZ (with values that
			 * differ from page to page) are not.  The effect varies with
			 * compression tool, but bzip2 for instance compresses about an
			 * order of magnitude worse if those headers are left in place.
			 *
			 * Rather than complicating AdvanceXLInsertBuffer itself (which is
			 * called in heavily-loaded circumstances as well as this lightly-
			 * loaded one) with variant behavior, we just use GetXLogBuffer
			 * (which itself calls the two methods we need) to get the pointer
			 * and zero most of the page.  Then we just zero the page header.
			 */
			currpos = GetXLogBuffer(CurrPos);
			MemSet(currpos, 0, SizeOfXLogShortPHD);

			CurrPos += XLOG_BLCKSZ;
		}
	}
	else
	{
		/* Align the end position, so that the next record starts aligned */
		CurrPos = MAXALIGN64(CurrPos);
	}
}}}

また、強制切り替えを行なった後、切り替わりでSWITCHが書き込まれたWALログは、即座にアーカイブできるようにしている。内部的にはPostmasterに対し、archiverを起こすためのシグナルが送られている。(&code(){PMSIGNAL_WAKEN_ARCHIVER};)


#geshi{{{
postgres=# select pg_switch_wal();
 pg_switch_wal 
---------------
 0/18000078
(1 row)

}}}

logレベルdebug5で出るメッセージ例は以下。

#geshi{{{
2019-03-20 15:20:12.692 JST [51362] DEBUG:  StartTransaction(1) name: unnamed; blockState: DEFAULT; state: INPROGRESS, xid/subid/cid: 0/1/0
2019-03-20 15:20:14.895 JST [51362] DEBUG:  CommitTransaction(1) name: unnamed; blockState: STARTED; state: INPROGRESS, xid/subid/cid: 0/1/0
2019-03-20 15:20:14.895 JST [50570] DEBUG:  executing archive command "cp pg_wal/000000010000000000000030 "/Users/guest/archivedir_p/000000010000000000000030""
2019-03-20 15:20:14.950 JST [50570] DEBUG:  archived write-ahead log file "000000010000000000000030"
}}}

以下はバックトレース(master: pg12)。

#geshi(c){{{
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 17.1
  * frame #0: 0x0000000106fe89ed postgres`XLogArchiveNotify(xlog="000000010000000000000019") at xlogarchive.c:531
    frame #1: 0x0000000106fe8afd postgres`XLogArchiveNotifySeg(segno=25) at xlogarchive.c:543
    frame #2: 0x0000000106fd1015 postgres`XLogWrite(WriteRqst=(Write = 436207616, Flush = 436207616), flexible=false) at xlog.c:2540
    frame #3: 0x0000000106fd027b postgres`XLogFlush(record=436207616) at xlog.c:2921
    frame #4: 0x0000000106fcf34d postgres`XLogInsertRecord(rdata=0x000000010783d1d0, fpw_lsn=0, flags='\0') at xlog.c:1150
    frame #5: 0x0000000106febd0f postgres`XLogInsert(rmid='\0', info='@') at xloginsert.c:462
    frame #6: 0x0000000106fdf8a5 postgres`RequestXLogSwitch(mark_unimportant=false) at xlog.c:9387
    frame #7: 0x0000000106fe9c79 postgres`pg_switch_wal(fcinfo=0x00007f8848808880) at xlogfuncs.c:292
    frame #8: 0x00000001071927ac postgres`ExecInterpExpr(state=0x00007f8848808798, econtext=0x00007f8848808488, isnull=0x00007ffee8d3d81f) at execExprInterp.c:625
    frame #9: 0x0000000107191b92 postgres`ExecInterpExprStillValid(state=0x00007f8848808798, econtext=0x00007f8848808488, isNull=0x00007ffee8d3d81f) at execExprInterp.c:1769
    frame #10: 0x00000001071e2a3b postgres`ExecEvalExprSwitchContext(state=0x00007f8848808798, econtext=0x00007f8848808488, isNull=0x00007ffee8d3d81f) at executor.h:312
    frame #11: 0x00000001071e29be postgres`ExecProject(projInfo=0x00007f8848808790) at executor.h:346
    frame #12: 0x00000001071e26f3 postgres`ExecResult(pstate=0x00007f8848808370) at nodeResult.c:136
    frame #13: 0x00000001071aa5d2 postgres`ExecProcNodeFirst(node=0x00007f8848808370) at execProcnode.c:445
    frame #14: 0x00000001071a3332 postgres`ExecProcNode(node=0x00007f8848808370) at executor.h:244
    frame #15: 0x000000010719ecf1 postgres`ExecutePlan(estate=0x00007f8848808118, planstate=0x00007f8848808370, use_parallel_mode=false, operation=CMD_SELECT, sendTuples=true, numberTuples=0, direction=ForwardScanDirection, dest=0x00007f8847823650, execute_once=true) at execMain.c:1643
    frame #16: 0x000000010719ebb2 postgres`standard_ExecutorRun(queryDesc=0x00007f8848802d18, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:362
    frame #17: 0x000000010719e982 postgres`ExecutorRun(queryDesc=0x00007f8848802d18, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:306
    frame #18: 0x00000001073eb006 postgres`PortalRunSelect(portal=0x00007f8847061518, forward=true, count=0, dest=0x00007f8847823650) at pquery.c:929
    frame #19: 0x00000001073ea9bc postgres`PortalRun(portal=0x00007f8847061518, count=9223372036854775807, isTopLevel=true, run_once=true, dest=0x00007f8847823650, altdest=0x00007f8847823650, completionTag="") at pquery.c:770
    frame #20: 0x00000001073e5fe8 postgres`exec_simple_query(query_string="select pg_switch_wal();") at postgres.c:1215
    frame #21: 0x00000001073e5188 postgres`PostgresMain(argc=1, argv=0x00007f8847025538, dbname="postgres", username="t-moriyasu") at postgres.c:4247
    frame #22: 0x0000000107321aa0 postgres`BackendRun(port=0x00007f8846d01720) at postmaster.c:4401
    frame #23: 0x0000000107320ea5 postgres`BackendStartup(port=0x00007f8846d01720) at postmaster.c:4092
    frame #24: 0x000000010731fdfa postgres`ServerLoop at postmaster.c:1705
    frame #25: 0x000000010731d6b9 postgres`PostmasterMain(argc=3, argv=0x00007f8846c03270) at postmaster.c:1378
    frame #26: 0x0000000107221339 postgres`main(argc=3, argv=0x00007f8846c03270) at main.c:228
    frame #27: 0x00007fff508df015 libdyld.dylib`start + 1
}}}

&code(){XLogArchiveNotify};関数でpostmasterにシグナルが送られていることが分かる。

&label(blockquote){引用}; [[backend/access/transam/xlog.c#XLogInsertRecord()>https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/access/transam/xlog.c;h=a93017feecffae7a7ff65d40b78a89556d55eb51;hb=refs/heads/REL_10_STABLE#l1133]]
#geshi(c){{{
	/*
	 * If this was an XLOG_SWITCH record, flush the record and the empty
	 * padding space that fills the rest of the segment, and perform
	 * end-of-segment actions (eg, notifying archiver).
	 */
	if (isLogSwitch)
	{
		TRACE_POSTGRESQL_WAL_SWITCH();
		XLogFlush(EndPos);

		/*
		 * Even though we reserved the rest of the segment for us, which is
		 * reflected in EndPos, we return a pointer to just the end of the
		 * xlog-switch record.
		 */
		if (inserted)
		{
			EndPos = StartPos + SizeOfXLogRecord;
			if (StartPos / XLOG_BLCKSZ != EndPos / XLOG_BLCKSZ)
			{
				uint64		offset = XLogSegmentOffset(EndPos, wal_segment_size);

				if (offset == EndPos % XLOG_BLCKSZ)
					EndPos += SizeOfXLogLongPHD;
				else
					EndPos += SizeOfXLogShortPHD;
			}
		}
	}
}}}


&label(blockquote){引用}; [[backend/access/transam/xlog.c#XLogWrite()>https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/access/transam/xlog.c;h=a93017feecffae7a7ff65d40b78a89556d55eb51;hb=refs/heads/REL_10_STABLE#l2504]]
#geshi(c){{{
// backend/access/transam/xlog.c#XLogWrite()

			/*
			 * If we just wrote the whole last page of a logfile segment,
			 * fsync the segment immediately.  This avoids having to go back
			 * and re-open prior segments when an fsync request comes along
			 * later. Doing it here ensures that one and only one backend will
			 * perform this fsync.
			 *
			 * This is also the right place to notify the Archiver that the
			 * segment is ready to copy to archival storage, and to update the
			 * timer for archive_timeout, and to signal for a checkpoint if
			 * too many logfile segments have been used since the last
			 * checkpoint.
			 */
			if (finishing_seg)
			{
				issue_xlog_fsync(openLogFile, openLogSegNo);

				/* signal that we need to wakeup walsenders later */
				WalSndWakeupRequest();

				LogwrtResult.Flush = LogwrtResult.Write;	/* end of page */

				if (XLogArchivingActive())
					XLogArchiveNotifySeg(openLogSegNo); // Archiverに知らせる

				XLogCtl->lastSegSwitchTime = (pg_time_t) time(NULL);
				XLogCtl->lastSegSwitchLSN = LogwrtResult.Flush;

				/*
				 * Request a checkpoint if we've consumed too much xlog since
				 * the last one.  For speed, we first check using the local
				 * copy of RedoRecPtr, which might be out of date; if it looks
				 * like a checkpoint is needed, forcibly update RedoRecPtr and
				 * recheck.
				 */
				if (IsUnderPostmaster && XLogCheckpointNeeded(openLogSegNo))
				{
					(void) GetRedoRecPtr();
					if (XLogCheckpointNeeded(openLogSegNo))
						RequestCheckpoint(CHECKPOINT_CAUSE_XLOG);
				}
			}
		}
}}}


&label(warn){参考};

- [[backend/access/transam/xlogarchive.c>https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/access/transam/xlogarchive.c;h=7825cfe532e2436115f26feee8d9502a24f340e1;hb=refs/heads/REL_10_STABLE#l491]] - &size(11){&color(gray){https://git.postgresql.org/gitweb/?p=postgresql.git;a=shortlog;h=refs/heads/REL_10_STABLE};};
* XLogArchiveNotifyのコールグラフ [#w44609ca]

Archiverを起こす人は誰か、参考までにコールグラフを以下に示す。

#geshi(c){{{
XLogArchiveNotify(const char *) : void
	KeepFileRestoredFromArchive(const char *, const char *) : void
		readTimeLineHistory(TimeLineID) : List *
			rescanLatestTimeLine() : _Bool
			StartReplication(StartReplicationCmd *) : void
			WaitForWALToBecomeAvailable(XLogRecPtr, _Bool, _Bool, XLogRecPtr) : _Bool
			XLogFileReadAnyTLI(XLogSegNo, int, int) : int
			XLogReadDetermineTimeline(XLogReaderState *, XLogRecPtr, uint32) : void
			XLogSendPhysical() : void
		restoreTimeLineHistoryFiles(TimeLineID, TimeLineID) : void
			rescanLatestTimeLine() : _Bool
			StartupXLOG() : void
		XLogFileRead(XLogSegNo, int, TimeLineID, int, _Bool) : int
			WaitForWALToBecomeAvailable(XLogRecPtr, _Bool, _Bool, XLogRecPtr) : _Bool
			XLogFileReadAnyTLI(XLogSegNo, int, int) : int (2 一致)
	StartupXLOG() : void
		InitPostgres(const char *, Oid, const char *, Oid, char *, _Bool) : void
			AutoVacLauncherMain(int, char * *) : void
			AutoVacWorkerMain(int, char * *) : void
			BackgroundWorkerInitializeConnection(const char *, const char *, uint32) : void
			BackgroundWorkerInitializeConnectionByOid(Oid, Oid, uint32) : void
			BootstrapModeMain() : void
			PostgresMain(int, char * *, const char *, const char *) : void
		StartupProcessMain() : void
			AuxiliaryProcessMain(int, char * *) : void
	WalReceiverMain() : void
		AuxiliaryProcessMain(int, char * *) : void
			main(int, char * *) : int
			StartChildProcess(AuxProcType) : pid_t
				MaybeStartWalReceiver() : void
				PostmasterMain(int, char * *) : void
				PostmasterStateMachine() : void (2 一致)
				reaper(int) : void (3 一致)
				ServerLoop() : int (3 一致)
				sigusr1_handler(int) : void (2 一致)
	writeTimeLineHistory(TimeLineID, TimeLineID, XLogRecPtr, char *) : void
		StartupXLOG() : void
			InitPostgres(const char *, Oid, const char *, Oid, char *, _Bool) : void
				AutoVacLauncherMain(int, char * *) : void
				AutoVacWorkerMain(int, char * *) : void
				BackgroundWorkerInitializeConnection(const char *, const char *, uint32) : void
				BackgroundWorkerInitializeConnectionByOid(Oid, Oid, uint32) : void
				BootstrapModeMain() : void
				PostgresMain(int, char * *, const char *, const char *) : void
			StartupProcessMain() : void
				AuxiliaryProcessMain(int, char * *) : void
	XLogArchiveCheckDone(const char *) : _Bool
		CleanupBackupHistory() : void
			do_pg_stop_backup(char *, _Bool, TimeLineID *) : XLogRecPtr
				perform_base_backup(basebackup_options *) : void
				pg_stop_backup_v2(FunctionCallInfo) : Datum (2 一致)
				pg_stop_backup(FunctionCallInfo) : Datum
		RemoveOldXlogFiles(XLogSegNo, XLogRecPtr, XLogRecPtr) : void
			CreateCheckPoint(int) : void
				CheckpointerMain() : void
					AuxiliaryProcessMain(int, char * *) : void
				RequestCheckpoint(int) : void
					createdb(ParseState *, const CreatedbStmt *) : Oid (2 一致)
					do_pg_start_backup(const char *, _Bool, TimeLineID *, StringInfo, List * *, StringInfo, _Bool, _Bool) : XLogRecPtr
					dropdb(const char *, _Bool) : void
					DropTableSpace(DropTableSpaceStmt *) : void
					movedb(const char *, const char *) : void (2 一致)
					standard_ProcessUtility(PlannedStmt *, const char *, ProcessUtilityContext, ParamListInfo, QueryEnvironment *, DestReceiver *, char *) : void
					StartupXLOG() : void (2 一致)
					XLogPageRead(XLogReaderState *, XLogRecPtr, int, XLogRecPtr, char *, TimeLineID *) : int
					XLogWrite(XLogwrtRqst, _Bool) : void
				ShutdownXLOG(int, Datum) : void
					CheckpointerMain() : void
					InitPostgres(const char *, Oid, const char *, Oid, char *, _Bool) : void
				StartupXLOG() : void
					InitPostgres(const char *, Oid, const char *, Oid, char *, _Bool) : void
					StartupProcessMain() : void
			CreateRestartPoint(int) : _Bool
				CheckpointerMain() : void
				ShutdownXLOG(int, Datum) : void
	XLogArchiveNotifySeg(XLogSegNo) : void
		XLogWrite(XLogwrtRqst, _Bool) : void
			AdvanceXLInsertBuffer(XLogRecPtr, _Bool) : void
				GetXLogBuffer(XLogRecPtr) : char *
				XLogBackgroundFlush() : _Bool
			XLogBackgroundFlush() : _Bool
				WalSndWaitForWal(XLogRecPtr) : XLogRecPtr
				WalWriterMain() : void
			XLogFlush(XLogRecPtr) : void
				CheckPointReplicationOrigin() : void
				CreateCheckPoint(int) : void
				CreateEndOfRecoveryRecord() : void
				EndPrepare(GlobalTransaction) : void
				finish_sync_worker() : void
				FlushBuffer(BufferDesc *, SMgrRelation) : void
				RecordTransactionAbortPrepared(TransactionId, int, TransactionId *, int, RelFileNode *, const char *) : void
				RecordTransactionCommit() : TransactionId
				RecordTransactionCommitPrepared(TransactionId, int, TransactionId *, int, RelFileNode *, int, SharedInvalidationMessage *, _Bool, const char *) : void
				RelationTruncate(Relation, BlockNumber) : void
				ReplicationSlotReserveWal() : void
				replorigin_get_progress(RepOriginId, _Bool) : XLogRecPtr
				replorigin_session_get_progress(_Bool) : XLogRecPtr
				SlruPhysicalWritePage(SlruCtl, int, int, SlruFlush) : _Bool
				smgr_redo(XLogReaderState *) : void
				write_relmap_file(_Bool, RelMapFile *, _Bool, _Bool, _Bool, Oid, Oid, const char *) : void
				WriteMTruncateXlogRec(Oid, MultiXactId, MultiXactId, MultiXactOffset, MultiXactOffset) : void
				WriteTruncateXlogRec(int, TransactionId, Oid) : void
				xact_redo_commit(xl_xact_parsed_commit *, TransactionId, XLogRecPtr, RepOriginId) : void (2 一致)
				XLogInsertRecord(XLogRecData *, XLogRecPtr, uint8) : XLogRecPtr
				XLogReportParameters() : void
	XLogWalRcvWrite(char *, Size, XLogRecPtr) : void
		XLogWalRcvProcessMsg(unsigned char, char *, Size) : void
			WalReceiverMain() : void
				AuxiliaryProcessMain(int, char * *) : void
}}}

* 参考リンク [#p7aa34cf]

- [[25.3. 継続的アーカイブとポイントインタイムリカバリ(PITR)>https://www.postgresql.jp/document/10/html/continuous-archiving.html]] - - &size(11){&color(gray){on https://www.postgresql.jp/document/10/html/continuous-archiving.html};};
- [[PostgreSQLのarchiverの挙動を調べた>https://qiita.com/U_ikki/items/dd9a58857a4ffb84f97d]] - &size(11){&color(gray){on https://qiita.com/U_ikki/items/dd9a58857a4ffb84f97d]};};
- [[あなたの知らないPostgreSQL監視の世界>https://www.slideshare.net/naka24nori/postgre-sql-55593111]] - &size(11){&color(gray){on https://www.slideshare.net/naka24nori/postgre-sql-55593111};};

トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
目次
ダブルクリックで閉じるTOP | 閉じる
GO TO TOP