PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wäre es während der Ausführung von PITR möglich, in PostgreSQL anzuhalten/fortzusetzen?

Ja, wirklich möglich und von PostgreSQL intelligent gehandhabt. Um dies zu demonstrieren, muss ich zuerst nach der Standardtechnik der Point-in-Time-Wiederherstellung in PostgreSQL vorgehen. Verschiedene Bücher/Artikel/Blogs wurden von außergewöhnlichen Autoren sehr gut demonstriert, daher gehe ich nicht ins Detail, wie es geht, sondern gehe direkt zum Thema über, d.h. wie man pausiert, während man sich mit der gleichen Technik erholt. Ich habe wohl einen mathematischen Ausdruck aus PITR als „PITR =(Last Filesystem Backup(LFB) + WAL Archives created after LFB + Un-Archived WAL’s in current $PGDATA/pg_xlogs)“ hervorgebracht. Zum besseren Verständnis habe ich dies grafisch dargestellt, um den Gedanken klarer zu machen:(Entschuldigung, dieser Blog ist etwas lang, unwissentlich ist es passiert, als ich in Details des Konzepts gegangen bin)

PITR-Schritte, die mit geringfügigen Änderungen folgen werden, über die ich bald sprechen werde:

Schritt 1. Stellen Sie die neueste Sicherung auf Dateisystemebene (FSB) an einem beliebigen Ort wieder her, an dem die Wiederherstellung geplant ist.
Schritt 2. Wenn FSB tar ist, entpacken Sie es und bereinigen Sie das pg_xlog-Verzeichnis, wobei archive_status übrig bleibt. Wenn die Sicherung dieses Verzeichnis ausgeschlossen hat, erstellen Sie das leere Verzeichnis pg_xlog im FSB.
Schritt 3. Kopieren Sie nicht archivierte WALs aus dem abgestürzten Cluster $PGDATA/pg_xlog in $FSB/pg_xlog (Schritt 2)
Schritt 4. Löschen Sie die postmaster.pid aus dem FSB-Verzeichnis.
Schritt 5. Erstellen Sie die Datei recovery.conf im FSB-Verzeichnis.
Schritt 6. Starten Sie den Cluster (FSB).

Wir sollten die Frage stellen, wann die Wiederherstellung erforderlich ist. Vielleicht, um mehrere Basiswiederherstellungen oder Rollforward-Wiederherstellungen zu verhindern, aber zwischendurch einchecken oder bestimmte Tabellendaten oder Interessen zurücksetzen, um zu sehen, wie weit sie wiederhergestellt wurden :). Denken Sie daran, dass eine Pause in der Erholung bedeutet, dass Sie sich während der Erholung verbinden können. Um dies zu skizzieren, habe ich eine Situation im Diagramm einer bestimmten Tabellenzeilenverbesserung bis zu einem Missgeschick reproduziert.

Aus dem obigen Diagramm geht hervor, dass die Zeilen einer DEMO-Tabelle 10.00.000 waren, als eine Sicherung auf Dateisystemebene ($PGDATA) durchgeführt wurde, und 40.00.000 Zeilen vor dem Absturz. In meiner lokalen VM habe ich die Situation auf Grund von TIME statt date.

gemacht

Voraussetzung:
1. Sicherung auf Dateisystemebene bei DEMO-Tabellen mit 10.00.000 Zeilen.
2. Von diesem Zeitpunkt an, WAL-Archive vor dem Absturz, wobei die DEMO-Tabelle 40.00.000 Zeilen enthält.
3. Speicherort des WAL-Archivs:/opt/PostgreSQL/9.3/archives.
4. Datenverzeichnis:/opt/PostgreSQL/9.3/data (PGDATA)
5. Backup-Speicherort:/opt/PostgreSQL/9.3/backups

Denken Sie daran, dass das Arbeiten mit der Pausenwiederherstellung obligatorische Änderungen im Hauptcluster ($PGDATA) „wal_level“ auf „hot_standby“ und im Wiederherstellungscluster (Sicherung auf Dateisystemebene) „hot_standby“ auf „ON“ setzen muss. Ich habe diese Änderungen am Hauptcluster vorgenommen, den Cluster neu gestartet, damit sie wirksam werden, und die Sicherung eingeleitet. Wenn es Ihnen nichts ausmacht, notieren Sie es sich einfach als Demo, also sind meine WAL-Archive möglicherweise keine gigantischen Nummern, da sie in wenigen Nummern vorhanden sind. Ich habe hier auch WAL-Archive aufgelistet, die vom Zeitpunkt der Sicherung bis zum Absturz generiert wurden.

-bash-4.1$ psql -c "select count(*), now() from demo;"
count | now
---------+-------------------------------
1000000 | 2014-04-04 15:06:04.036928-07
(1 row)

-bash-4.1$ pg_basebackup -D /opt/PostgreSQL/9.3/backup/data_pitr -- I have my $PGDATA, $PGUSER, $PGPORT set, so its a straight command in my case
NOTICE: pg_stop_backup complete, all required WAL segments have been archived

Aktueller Stand der WAL-Archive und $PGDATA/pg_xlog

-bash-4.1$ ls -lrth /opt/PostgreSQL/9.3/archives
-rw------- 1 postgres postgres 16M Apr 4 16:01 00000001000000000000001C
-rw------- 1 postgres postgres 16M Apr 4 16:01 00000001000000000000001D
-rw------- 1 postgres postgres 289 Apr 4 16:06 00000001000000000000001E.000000C8.backup
-rw------- 1 postgres postgres 16M Apr 4 16:06 00000001000000000000001E

-bash-4.1$ ls -lrth /opt/PostgreSQL/9.3/data/pg_xlog | tail -4
-rw------- 1 postgres postgres 289 Apr 4 16:06 00000001000000000000001E.000000C8.backup
-rw------- 1 postgres postgres 16M Apr 4 16:06 00000001000000000000001E
-rw------- 1 postgres postgres 16M Apr 4 16:06 00000001000000000000001F
drwx------ 2 postgres postgres 4.0K Apr 4 16:13 archive_status

Nun gut, wir haben die Sicherungskopie, lassen Sie einige Aufzeichnungen in drei Teilen einfügen, indem Sie die Zeit notieren, damit die Wiederherstellung angehalten und zusätzlich die WALs angezeigt werden, die seit der Zeit des FSB produziert wurden.

-bash-4.1$ psql -c "insert into demo values (generate_series(1,1000000));"
INSERT 0 1000000
-bash-4.1$ psql -c "select count(*),now() from demo;"
count | now
---------+-------------------------------
2000000 | 2014-04-04 16:06:34.941615-07
(1 row)
-bash-4.1$ psql -c "insert into demo values (generate_series(1,1000000));"
INSERT 0 1000000
-bash-4.1$ psql -c "select count(*),now() from demo;"
count | now
---------+-------------------------------
3000000 | 2014-04-04 16:10:31.136725-07
(1 row)
-bash-4.1$ psql -c "insert into demo values (generate_series(1,1000000));"
INSERT 0 1000000
-bash-4.1$ psql -c "select count(*),now() from demo;"
count | now
---------+-------------------------------
4000000 | 2014-04-04 16:13:00.136725-07
(1 row)

Überprüfen Sie die Anzahl der während des INSERT erzeugten WALs.

-bash-4.1$ ls -lrth /opt/PostgreSQL/9.3/archives
-rw------- 1 postgres postgres 289 Apr 4 16:06 00000001000000000000001E.000000C8.backup
-rw------- 1 postgres postgres 16M Apr 4 16:06 00000001000000000000001E
-rw------- 1 postgres postgres 16M Apr 4 16:06 00000001000000000000001F
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000020
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000021
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000022
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000023
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000024
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000025
-rw------- 1 postgres postgres 16M Apr 4 16:06 000000010000000000000026
-rw------- 1 postgres postgres 16M Apr 4 16:10 000000010000000000000027
-rw------- 1 postgres postgres 16M Apr 4 16:10 000000010000000000000028
-rw------- 1 postgres postgres 16M Apr 4 16:10 000000010000000000000029
-rw------- 1 postgres postgres 16M Apr 4 16:10 00000001000000000000002A
-rw------- 1 postgres postgres 16M Apr 4 16:13 00000001000000000000002B

Angenommen, an diesem Punkt ist ein Missgeschick passiert und Sie müssen eine Wiederherstellung mit FSB + WAL-Archiven + nicht archivierten WALs (falls vorhanden) durchführen. Während der Wiederherstellung möchte ich dreimal anhalten, um jede Wiederherstellung von 20.00.000, 30.00.000 und 40.00.000 Zeilen der DEMO-Tabelle anzuzeigen, indem ich eine Verbindung zur Datenbank im schreibgeschützten Modus herstelle. Für jede Wiederaufnahme der Wiederherstellung ist ein Neustart des Wiederherstellungsclusters erforderlich, indem auf die neue Zeitachse in recovery.conf/recovery_target_time gestoßen wird. Außerdem müssen wir in $FSB/postgresql.conf hot_standby=on setzen. Hier ist meine recovery.conf-Datei:

-bash-4.1$ more recovery.conf
pause_at_recovery_target = true
#recovery_target_time = '2014-04-04 16:06:34' # For 2 lakh records
#recovery_target_time = '2014-04-04 16:10:31' # For 3 lakh records
#recovery_target_time = '2014-04-04 16:13:00' # For 4 lakh records
restore_command = 'cp /opt/PostgreSQL/9.3/archives/%f %p'

Beginnen wir mit der Wiederherstellung von 20.00.000 Datensätzen:

-bash-4.1$ /opt/PostgreSQL/9.3/bin/pg_ctl -D /opt/PostgreSQL/9.3/data_pitr/ start
server starting

Now in logs:

-bash-4.1$ more postgresql-2014-04-04_162524.log
2014-04-04 16:25:24 PDT-24187---[] LOG: starting point-in-time recovery to 2014-02-06 18:48:56-08
2014-04-04 16:25:24 PDT-24187---[] LOG: restored log file "00000001000000000000001E" from archive
2014-04-04 16:25:24 PDT-24187---[] LOG: redo starts at 0/1E0000C8
2014-04-04 16:25:24 PDT-24187---[] LOG: consistent recovery state reached at 0/1E000190
2014-04-04 16:25:24 PDT-24185---[] LOG: database system is ready to accept read only connections
2014-04-04 16:25:24 PDT-24187---[] LOG: restored log file "00000001000000000000001F" from archive
2014-04-04 16:25:24 PDT-24187---[] LOG: restored log file "000000010000000000000020" from archive
2014-04-04 16:25:25 PDT-24187---[] LOG: restored log file "000000010000000000000021" from archive
2014-04-04 16:25:25 PDT-24187---[] LOG: restored log file "000000010000000000000022" from archive
2014-04-04 16:25:25 PDT-24187---[] LOG: recovery stopping before commit of transaction 1833, time 2014-04-04 16:06:23.893487-07
2014-04-04 16:25:25 PDT-24187---[] LOG: recovery has paused
2014-04-04 16:25:25 PDT-24187---[] HINT: Execute pg_xlog_replay_resume() to continue

Cool, sehen Sie in den Protokollen, dass es angehalten wurde, und einen intelligenten HINWEIS, der Sie zum Fortsetzen auffordert. Wenn die Wiederherstellung zufriedenstellend war, können Sie sie hier fortsetzen, indem Sie „select pg_xlog_replay_resume();“ aufrufen (Sie können es überprüfen). Lassen Sie uns jetzt nicht fortfahren, überprüfen Sie jedoch die Anzahl der wiederhergestellten Zeilen, indem Sie sich mit dem Server verbinden.

-bash-4.1$ psql -c "select count(*),pg_is_in_recovery() from demo;"
count | pg_is_in_recovery
---------+-------------------
2000000 | t
(1 row)

Gut, es hat den Punkt erreicht und dort angehalten, wo ich es angefordert habe. Gehen wir noch einen Schritt weiter, um 30.00.000 Zeilen wiederherzustellen. Legen Sie nun die nächste Zeitachse in recovery.conf/recovery_target_time fest und starten Sie den Cluster neu.

2014-04-04 16:28:40 PDT-24409---[] LOG:  restored log file "00000001000000000000002A" from archive
2014-04-04 16:28:40 PDT-24409---[] LOG: recovery stopping before commit of transaction 1836, time 2014-04-04 16:10:40.141175-07
2014-04-04 16:28:40 PDT-24409---[] LOG: recovery has paused
2014-04-04 16:28:40 PDT-24409---[] HINT: Execute pg_xlog_replay_resume() to continue.

-bash-4.1$ psql -c "select count(*),pg_is_in_recovery() from demo;"
count | pg_is_in_recovery
---------+-------------------
3000000 | t
(1 row)

Schön …, geben wir den letzten Versuch, bei 40.00.000 Zeilen anzuhalten.

2014-04-04 20:09:07 PDT-4723---[] LOG:  restored log file "00000001000000000000002B" from archive
cp: cannot stat `/opt/PostgreSQL/9.3/archives/00000001000000000000002C': No such file or directory
2014-04-04 20:09:07 PDT-4723---[] LOG: redo done at 0/2B0059A0
2014-04-04 20:09:07 PDT-4723---[] LOG: last completed transaction was at log time 2014-04-04 16:11:12.264512-07
2014-04-04 20:09:07 PDT-4723---[] LOG: restored log file "00000001000000000000002B" from archive
2014-04-04 20:09:07 PDT-4723---[] LOG: restored log file "00000002.history" from archive
2014-04-04 20:09:07 PDT-4723---[] LOG: restored log file "00000003.history" from archive
2014-04-04 20:09:07 PDT-4723---[] LOG: restored log file "00000004.history" from archive
cp: cannot stat `/opt/PostgreSQL/9.3/archives/00000005.history': No such file or directory
2014-04-04 20:09:07 PDT-4723---[] LOG: selected new timeline ID: 5
cp: cannot stat `/opt/PostgreSQL/9.3/archives/00000001.history': No such file or directory
2014-04-04 20:09:07 PDT-4723---[] LOG: archive recovery complete
2014-04-04 20:09:08 PDT-4721---[] LOG: database system is ready to accept connections
2014-04-04 20:09:08 PDT-4764---[] LOG: autovacuum launcher started

-bash-4.1$ psql -c "select count(*),pg_is_in_recovery() from demo;"
count | pg_is_in_recovery
---------+-------------------
4000000 | f
(1 row)

Hoppla, was ist passiert, warum hat es nicht angehalten und was beschwert es sich?. Denken Sie daran, wenn zum Zeitpunkt von recovery_target_time keine WAL-Archive vorhanden sind, wird es nicht anhalten und erwarten, dass es den letzten Punkt erreicht hat, und die Datenbank für READ/WRITE öffnen. Stellen Sie in Protokollen ohne viel Aufwand fest, dass nach der Datei „00000001000000000000002C“ gesucht wurde, die nicht verfügbar ist, da der Cluster zu diesem Zeitpunkt abgestürzt ist. Einige erkennen dieses Verhalten vielleicht nicht an, aber es ist eine Tatsache und sinnvoll, wenn keine WAL-Archive vorhanden sind, dann gibt es keinen Grund, die Wiederherstellung anzuhalten. Wenn es überhaupt erforderlich ist, auch nach keinen WAL-Archiven anzuhalten, verwenden Sie standby_mode=’on’ (HOT_STANDBY), bei dieser Methode kommt es nicht aus der Wiederherstellung, sondern wartet auf WAL-Archive.

Hoffe, es war nützlich.