sql >> Database >  >> RDS >> PostgreSQL

Zou het tijdens het uitvoeren van PITR mogelijk zijn om te pauzeren/hervatten in PostgreSQL?

Ja, echt mogelijk en slim afgehandeld door PostgreSQL. Om dit te demonstreren, moet ik eerst de standaardtechniek van Point in Time Recovery in PostgreSQL volgen. Verschillende boeken/artikelen/blogs zijn buitengewoon goed gedemonstreerd door buitengewone auteurs, daarom ga ik niet in op details over hoe het moet, maar ga rechtstreeks naar het onderwerp, d.w.z. hoe te pauzeren terwijl u herstelt met dezelfde techniek. Ongetwijfeld heb ik een wiskundige uitdrukking uit PITR naar voren gebracht als "PITR =(Laatste bestandssysteemback-up (LFB) + WAL-archieven gegenereerd na LFB + niet-gearchiveerde WAL's in huidige $ PGDATA / pg_xlogs)". Voor een beter begrip heb ik dit in een grafiek gezet, in het licht van het feit dat het de gedachte duidelijker maakt:(Sorry, deze blog is een beetje lang, onbewust gebeurde het terwijl ik dieper inging op het concept)

PITR-stappen, die zullen volgen met kleine veranderingen waar ik het binnenkort over heb:

Stap 1. Zet de meest recente back-up op bestandssysteemniveau (FSB) terug naar elke locatie waar het herstel is gepland.
Stap 2. Als FSB tar is, untar het dan, en maak de pg_xlog directory schoon en laat archive_status achter. Als back-up deze map heeft uitgesloten, maak dan de lege pg_xlog map in FSB aan.
Stap 3. Kopieer niet-gearchiveerde WAL's van gecrashte cluster $PGDATA/pg_xlog naar $FSB/pg_xlog (stap 2)
Stap 4. Verwijder de postmaster.pid uit de FSB-directory.
Stap 5. Maak het recovery.conf-bestand in de FSB-directory.
Stap 6. Start het cluster (FSB).

We moeten de vraag stellen, wanneer het vereiste herstel wordt onderbroken?. Misschien om meerdere basisrestauraties of roll-forward recovery te voorkomen, maar check tussendoor of rollback een bepaalde tabelgegevens of interesse om te zien hoe ver het is hersteld :). Onthoud dat pauzeren in herstel betekent dat u verbinding kunt maken tijdens het herstellen. Om dit te schetsen, heb ik een situatie in de grafiek weergegeven van een bepaalde verbetering van de tabelrijen tot een ongeluk.

Uit het bovenstaande diagram blijkt dat de rijen van een DEMO-tabel 10.000.000 waren toen een back-up op bestandssysteemniveau ($ PGDATA) werd genomen en 40.000.000 rijen vóór de crash. In mijn lokale VM heb ik de situatie op basis van TIME gemaakt in plaats van datum.

Vereiste:
1. Back-up op bestandssysteemniveau wanneer DEMO-tabellen 10.000.000 rijen hebben.
2. Vanaf dat moment, WAL Archief voor crash waar DEMO-tabel met 40.000.000 rijen.
3. WAL Archief Locatie:/opt/PostgreSQL/9.3/archives.
4. Gegevensmap:/opt/PostgreSQL/9.3/data (PGDATA)
5. Back-uplocatie:/opt/PostgreSQL/9.3/backups

Houd er rekening mee dat werken met pauzeherstel verplichte wijzigingen vereist op het hoofdcluster ($ PGDATA) "wal_level" ingesteld op "hot_standby" en op herstelcluster (back-up op bestandssysteemniveau) "hot_standby" ingesteld op "AAN". Ik heb deze wijzigingen aangebracht in het hoofdcluster, het cluster opnieuw gestart om van kracht te worden en de back-up gestart. Als je het niet erg vindt, maak dan een notitie, het is gewoon een demo, dus mijn WAL-archieven zijn misschien geen gigantische aantallen, want het zijn er maar in een paar aantallen. Ik heb hier ook WAL-archieven vermeld, die zijn gegenereerd vanaf het moment van back-up tot crash.

-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

Huidige status van WAL-archieven en $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

Goed nu, we hebben de reservekopie, laten we een paar records in drie delen INSERT door de tijd te noteren, dus het zal helpen om het herstel te pauzeren en bovendien de WAL's te zien die zijn geproduceerd uit de tijd van FSB.

-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)

Controleer het aantal WAL's dat tijdens de INSERT is geproduceerd.

-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

Stel dat er op dit moment een ongeluk is gebeurd en dat u herstel moet uitvoeren met FSB + WAL-archieven + niet-gearchiveerde WAL's (indien aanwezig). Tijdens het herstel wil ik drie keer pauzeren om elk herstel van 20.000.000, 30.000.000 en 40.000.000 rijen DEMO-tabel te zien door verbinding te maken met de database in de modus ALLEEN LEZEN. Voor elke hervatting van het herstel moet het herstelcluster opnieuw worden opgestart door naar de nieuwe tijdlijn te gaan in recovery.conf/recovery_target_time. Ook moeten we in $FSB/postgresql.conf hot_standby=on instellen. Hier is mijn recovery.conf-bestand:

-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'

Laten we beginnen met het herstel van 20.000.000 records:

-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, zie in logs dat het is gepauzeerd en een slimme HINT die vraagt ​​om door te gaan. Hier, als het herstel bevredigend was, kunt u het hervatten door "select pg_xlog_replay_resume();" aan te roepen (u kunt het bekijken). Laten we nu niet verder gaan, maar controleer het aantal herstelde rijen door verbinding te maken met de server.

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

Goed, het heeft het punt bereikt en gepauzeerd waar ik had gevraagd. Laten we nog een stap verder gaan om 30.000.000 rijen te herstellen. Stel nu de volgende tijdlijn in recovery.conf/recovery_target_time in en start het cluster opnieuw.

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)

Leuk..., laten we de laatste poging doen om te pauzeren bij 40.000.000 rijen.

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)

Oeps, wat is er gebeurd, waarom is het niet gepauzeerd en wat klaagt het?. Houd er rekening mee dat als er geen WAL-archieven aanwezig zijn op het moment van recovery_target_time, het niet zal pauzeren en verwachten dat het op het laatste punt is aangekomen en de database zal openen voor LEZEN/SCHRIJVEN. In logs, zonder veel uitstrekking, blijkt dat het op jacht was naar bestand "00000001000000000000002C" dat niet beschikbaar is, omdat het cluster op dat moment is gecrasht. Sommigen erkennen dit gedrag misschien niet, maar het is een feit en is logisch als er geen WAL-archieven aanwezig zijn, dan is er geen reden om het herstel te onderbreken. Als het überhaupt nodig is om te pauzeren, zelfs nadat er geen WAL-archieven zijn, maak dan gebruik van standby_mode='on' (HOT_STANDBY), bij deze methode komt het niet uit herstel maar wacht op WAL-archieven.

Ik hoop dat het nuttig was.


  1. Opgeslagen procedure aanroepen met tabelwaardeparameter uit java

  2. SQL Server 2016:OLTP-verbeteringen in het geheugen

  3. PostgreSQL-prestaties benchmarken

  4. PostgreSQL:prestatie pg_dump, pg_restore verbeteren