2012-10-02 12:37:19 +02:00
|
|
|
/*
|
|
|
|
* timeline.h
|
|
|
|
*
|
|
|
|
* Functions for reading and writing timeline history files.
|
|
|
|
*
|
2016-01-02 19:33:40 +01:00
|
|
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
2012-10-02 12:37:19 +02:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
* src/include/access/timeline.h
|
|
|
|
*/
|
|
|
|
#ifndef TIMELINE_H
|
|
|
|
#define TIMELINE_H
|
|
|
|
|
|
|
|
#include "access/xlogdefs.h"
|
|
|
|
#include "nodes/pg_list.h"
|
|
|
|
|
2012-12-04 14:28:58 +01:00
|
|
|
/*
|
|
|
|
* A list of these structs describes the timeline history of the server. Each
|
|
|
|
* TimeLineHistoryEntry represents a piece of WAL belonging to the history,
|
|
|
|
* from newest to oldest. All WAL positions between 'begin' and 'end' belong to
|
|
|
|
* the timeline represented by the entry. Together the 'begin' and 'end'
|
|
|
|
* pointers of all the entries form a contiguous line from beginning of time
|
|
|
|
* to infinity.
|
|
|
|
*/
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
TimeLineID tli;
|
2013-05-29 22:58:43 +02:00
|
|
|
XLogRecPtr begin; /* inclusive */
|
2015-09-15 16:38:01 +02:00
|
|
|
XLogRecPtr end; /* exclusive, InvalidXLogRecPtr means
|
|
|
|
* infinity */
|
2012-12-04 14:28:58 +01:00
|
|
|
} TimeLineHistoryEntry;
|
|
|
|
|
2012-10-02 12:37:19 +02:00
|
|
|
extern List *readTimeLineHistory(TimeLineID targetTLI);
|
|
|
|
extern bool existsTimeLineHistory(TimeLineID probeTLI);
|
|
|
|
extern TimeLineID findNewestTimeLine(TimeLineID startTLI);
|
|
|
|
extern void writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
|
2012-12-04 14:28:58 +01:00
|
|
|
XLogRecPtr switchpoint, char *reason);
|
Allow a streaming replication standby to follow a timeline switch.
Before this patch, streaming replication would refuse to start replicating
if the timeline in the primary doesn't exactly match the standby. The
situation where it doesn't match is when you have a master, and two
standbys, and you promote one of the standbys to become new master.
Promoting bumps up the timeline ID, and after that bump, the other standby
would refuse to continue.
There's significantly more timeline related logic in streaming replication
now. First of all, when a standby connects to primary, it will ask the
primary for any timeline history files that are missing from the standby.
The missing files are sent using a new replication command TIMELINE_HISTORY,
and stored in standby's pg_xlog directory. Using the timeline history files,
the standby can follow the latest timeline present in the primary
(recovery_target_timeline='latest'), just as it can follow new timelines
appearing in an archive directory.
START_REPLICATION now takes a TIMELINE parameter, to specify exactly which
timeline to stream WAL from. This allows the standby to request the primary
to send over WAL that precedes the promotion. The replication protocol is
changed slightly (in a backwards-compatible way although there's little hope
of streaming replication working across major versions anyway), to allow
replication to stop when the end of timeline reached, putting the walsender
back into accepting a replication command.
Many thanks to Amit Kapila for testing and reviewing various versions of
this patch.
2012-12-13 18:00:00 +01:00
|
|
|
extern void writeTimeLineHistoryFile(TimeLineID tli, char *content, int size);
|
Fix more issues with cascading replication and timeline switches.
When a standby server follows the master using WAL archive, and it chooses
a new timeline (recovery_target_timeline='latest'), it only fetches the
timeline history file for the chosen target timeline, not any other history
files that might be missing from pg_xlog. For example, if the current
timeline is 2, and we choose 4 as the new recovery target timeline, the
history file for timeline 3 is not fetched, even if it's part of this
server's history. That's enough for the standby itself - the history file
for timeline 4 includes timeline 3 as well - but if a cascading standby
server wants to recover to timeline 3, it needs the history file. To fix,
when a new recovery target timeline is chosen, try to copy any missing
history files from the archive to pg_xlog between the old and new target
timeline.
A second similar issue was with the WAL files. When a standby recovers from
archive, and it reaches a segment that contains a switch to a new timeline,
recovery fetches only the WAL file labelled with the new timeline's ID. The
file from the new timeline contains a copy of the WAL from the old timeline
up to the point where the switch happened, and recovery recovers it from the
new file. But in streaming replication, walsender only tries to read it
from the old timeline's file. To fix, change walsender to read it from the
new file, so that it behaves the same as recovery in that sense, and doesn't
try to open the possibly nonexistent file with the old timeline's ID.
2013-01-23 09:01:04 +01:00
|
|
|
extern void restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end);
|
2012-12-04 14:28:58 +01:00
|
|
|
extern bool tliInHistory(TimeLineID tli, List *expectedTLIs);
|
|
|
|
extern TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history);
|
Make pg_receivexlog and pg_basebackup -X stream work across timeline switches.
This mirrors the changes done earlier to the server in standby mode. When
receivelog reaches the end of a timeline, as reported by the server, it
fetches the timeline history file of the next timeline, and restarts
streaming from the new timeline by issuing a new START_STREAMING command.
When pg_receivexlog crosses a timeline, it leaves the .partial suffix on the
last segment on the old timeline. This helps you to tell apart a partial
segment left in the directory because of a timeline switch, and a completed
segment. If you just follow a single server, it won't make a difference, but
it can be significant in more complicated scenarios where new WAL is still
generated on the old timeline.
This includes two small changes to the streaming replication protocol:
First, when you reach the end of timeline while streaming, the server now
sends the TLI of the next timeline in the server's history to the client.
pg_receivexlog uses that as the next timeline, so that it doesn't need to
parse the timeline history file like a standby server does. Second, when
BASE_BACKUP command sends the begin and end WAL positions, it now also sends
the timeline IDs corresponding the positions.
2013-01-17 19:23:00 +01:00
|
|
|
extern XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history,
|
|
|
|
TimeLineID *nextTLI);
|
2012-10-02 12:37:19 +02:00
|
|
|
|
|
|
|
#endif /* TIMELINE_H */
|