sql >> Database teknologi >  >> RDS >> PostgreSQL

Mens du udfører PITR, ville det være muligt at pause/genoptage i PostgreSQL?

Ja, virkelig muligt og håndteret smart af PostgreSQL. For at demo dette skal jeg først tage efter standardteknikken Point in Time Recovery i PostgreSQL. Forskellige bøger/artikler/blogs demonstrerede ekstremt godt af ekstraordinære forfattere, derfor går jeg ikke i detaljer om, hvordan man gør det, men går direkte til emnet, dvs. hvordan man holder pause, mens man restituerer med samme teknik. Ganske vist fremsatte jeg et matematisk udtryk ud af PITR som "PITR =(Sidste filsystemsikkerhedskopiering(LFB) + WAL-arkiver genereret efter LFB + ikke-arkiverede WAL'er i nuværende $PGDATA/pg_xlogs)". For bedre forståelse har jeg sat dette ind i grafen, i lyset af, at det klarede tanken mere:(Beklager, denne blog er lidt lang, ubevidst skete det, mens jeg gik i detaljer om konceptet)

PITR-trin, som vil følge med små ændringer, som jeg snart taler om:

Trin 1. Gendan den seneste sikkerhedskopiering på filsystemniveau (FSB) til ethvert sted, hvor gendannelse er planlagt til at udføre.
Trin 2. Hvis FSB er tar, så fjern den og rens pg_xlog-mappen og forlader archive_status. Hvis backup har udelukket denne mappe, skal du oprette den tomme pg_xlog-mappe i FSB.
Trin 3. Kopier ikke-arkiverede WAL'er fra nedbrudte klynge $PGDATA/pg_xlog til $FSB/pg_xlog (trin 2)
Trin 4. Slet postmaster.pid fra FSB-biblioteket.
Trin 5. Opret filen recovery.conf i FSB-biblioteket.
Trin 6. Start klyngen (FSB).

Vi bør stille spørgsmål, når pause den nødvendige genopretning?. Måske for at forhindre flere basisgendannelser eller fremadgående gendannelse, men tjek ind imellem eller rollback en bestemt tabeldata eller interesse for at se, hvor langt den er gendannet :). Husk, pause i genoprettelsen betyder, at det giver mulighed for at oprette forbindelse, mens du genopretter. For at skitsere dette har jeg gengivet en situation i diagrammet med forbedring af en bestemt tabelrækker indtil et uheld.

Fra ovenstående diagram var det behagelige en DEMO-tabelrækker 10.00.000, når sikkerhedskopiering på filsystemniveau ($PGDATA) blev taget, og 40.00.000 rækker før nedbrud. I min lokale VM har jeg lavet situationen på grundlag af TIME i stedet for dato.

Forudsætning:
1. Sikkerhedskopiering på filsystemniveau, når DEMO-tabeller har 10.00.000 rækker.
2. Fra det tidspunkt fremad, WAL Arkiver før nedbrud, hvor DEMO tabel med 40.00.000 rækker.
3. WAL Archives Placering:/opt/PostgreSQL/9.3/archives.
4. Datakatalog :/opt/PostgreSQL/9.3/data (PGDATA)
5. Sikkerhedskopieringsplacering:/opt/PostgreSQL/9.3/backups

Husk, at arbejde med pausegendannelse kræver obligatoriske ændringer på hovedklyngen ($PGDATA) "wal_level" sat til "hot_standby" og på gendannelsesklyngen (backup på filsystemniveau) "hot_standby" sat til "ON". Jeg har foretaget disse ændringer til hovedklyngen, genstartet klyngen for at træde i kraft og påbegyndt sikkerhedskopieringen. Hvis du ikke har noget imod, noter det blot en demo, så mine WAL-arkiver er måske ikke gigantiske tal, da de er i få numre. Jeg har også angivet WAL-arkiver her, som blev genereret fra sikkerhedskopieringstidspunktet til nedbrud.

-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

Nuværende tilstand af WAL-arkiver og $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

Fint nu, vi har sikkerhedskopien, lader INSERT få optegnelser i tre dele ved at notere tiden, så det vil hjælpe med at sætte genoprettelsen på pause og desuden se WAL'erne produceret fra FSB's tid.

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

Tjek antallet af WAL'er, der er produceret under INSERT.

-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

Antag, at der skete et uheld på dette tidspunkt, og at du skal udføre gendannelse ved hjælp af FSB + WAL-arkiver + uarkiverede WAL'er (hvis nogen). Under gendannelse vil jeg holde pause tre gange for at se hver gendannelse af 20.00.000, 30.00.000 og 40.00.000 rækker af DEMO-tabel ved at oprette forbindelse til databasen i SKRIVEKUN-tilstand. For hvert genoptagelse af gendannelse skal du genstarte gendannelsesklyngen ved at gå til den nye tidslinje i recovery.conf/recovery_target_time. Også i $FSB/postgresql.conf skal vi indstille hot_standby=on. Her er min recovery.conf-fil:

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

Lad os begynde at genoprette 20.00.000 poster:

-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

Sejt, se i logfiler, at det er sat på pause og et smart TIP, der beder om at genoptage. Her, hvis genoprettelsen var tilfredsstillende, kan du genoptage den ved at kalde “select pg_xlog_replay_resume();”(Du kan tjekke det ud). Lad os ikke genoptage nu, men kontroller antallet af gendannet rækker ved at oprette forbindelse til serveren.

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

Godt, det er nået til det punkt og stoppet, hvor jeg bad om. Lad os gå et skridt mere for at genskabe 30.00.000 rækker. Indstil nu den næste tidslinje i recovery.conf/recovery_target_time og genstart klyngen.

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)

Dejligt…, lad os give det sidste forsøg på at holde pause ved 40.00.000 rækker.

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)

Ups, hvad skete der, hvorfor har den ikke holdt pause, og hvad klager den?. Husk, hvis der ikke er nogen WAL-arkiver til stede på tidspunktet for recovery_target_time, vil det ikke pause og forvente, da det er nået til det sidste punkt og åbne databasen for READ/WRITE. I logfiler, uden meget stræk, var den på jagt efter filen "00000000000000002C", som ikke er tilgængelig, fordi klyngen på det tidspunkt er gået ned. Nogle anerkender måske ikke denne adfærd, men dens kendsgerning og giver mening, når der ikke er nogen WAL-arkiver til stede, så er der ingen grund til at sætte genoprettelsen på pause. Hvis det overhovedet er nødvendigt at pause, selv efter ingen WAL-arkiver, så brug standby_mode='on' (HOT_STANDBY), i denne metode vil det ikke komme ud af gendannelse, men vente på WAL Archives.

Håber det var nyttigt.


  1. System.Data.OracleClient kræver Oracle-klientsoftware version 8.1.7

  2. PHP Fatal fejl:Klasse 'PDO' blev ikke fundet

  3. JDBC MySql-forbindelsespooling praktiserer for at undgå opbrugt forbindelsespulje

  4. Sådan tilføjer du en titel til en rapporthoved i Microsoft Access