sql >> Databasteknik >  >> RDS >> PostgreSQL

Skulle det vara möjligt att pausa/återuppta i PostgreSQL när du utför PITR?

Ja, verkligen möjligt och hanteras smart av PostgreSQL. För att demo detta måste jag först ta efter standardtekniken Point in Time Recovery i PostgreSQL. Olika böcker/artiklar/bloggar demonstrerade extremt bra av extraordinära författare, därför går jag inte in på detaljer om hur man gör det, men går direkt till ämnet, dvs hur man pausar medan man återhämtar sig med samma teknik. Förmodligen lägger jag fram ett matematiskt uttryck ur PITR som "PITR =(Last Filesystem Backup(LFB) + WAL Archives generated after LFB + Un-Archived WAL's in current $PGDATA/pg_xlogs)". För bättre förståelse har jag lagt detta i grafen, i ljuset av att det klarnar tanken mer:(Tyvärr, den här bloggen är lite lång, omedvetet hände det när man gick in i detaljer om konceptet)

PITR-steg, som kommer att följa med små förändringar som jag pratar om snart:

Steg 1. Återställ den senaste säkerhetskopian på filsystemnivå (FSB) till en plats där återställning är planerad att utföras.
Steg 2. Om FSB är tar, avtar du det och rengör pg_xlog-katalogen och lämnar archive_status. Om säkerhetskopiering har uteslutit den här katalogen, skapa den tomma pg_xlog-katalogen i FSB.
Steg 3. Kopiera oarkiverade WAL från kraschade kluster $PGDATA/pg_xlog till $FSB/pg_xlog (steg 2)
Steg 4. Ta bort postmaster.pid från FSB-katalogen.
Steg 5. Skapa filen recovery.conf i FSB-katalogen.
Steg 6. Starta klustret (FSB).

Vi bör ställa frågan, när pausa återhämtningen krävs?. Kanske, för att förhindra flera basåterställningar eller roll-forward-återställning men kolla emellan eller återställa en viss tabelldata eller intresse för att se hur långt den har återställts :). Kom ihåg att paus i återställning betyder att det tillåter att ansluta medan du återhämtar dig. För att beskriva detta har jag återgett en situation i diagrammet med en förbättring av en viss tabellrad tills ett missöde inträffade.

Från ovanstående diagram var det angenäma en DEMO-tabellrader 10.00.000 när säkerhetskopiering på filsystemnivå ($PGDATA) togs och 40.00.000 rader före kraschen. I min lokala VM har jag gjort situationen på grundval av TIME istället för datum.

Förutsättning:
1. Säkerhetskopiering på filsystemnivå när DEMO-tabeller har 10 00 000 rader.
2. Från den punkten och framåt, arkiverar WAL före kraschen där DEMO-tabellen har 40 00 000 rader.
3. WAL Archives Plats:/opt/PostgreSQL/9.3/archives.
4. Datakatalog:/opt/PostgreSQL/9.3/data (PGDATA)
5. Säkerhetskopieringsplats:/opt/PostgreSQL/9.3/backups

Tänk på att arbete med pausåterställning kräver obligatoriska ändringar på huvudklustret ($PGDATA) "wal_level" satt till "hot_standby" och på återställningsklustret (säkerhetskopiering på filsystemnivå) "hot_standby" satt till "ON". Jag har gjort dessa ändringar i huvudklustret, startat om klustret för att träda i kraft och initierat säkerhetskopieringen. Om du inte har något emot att anteckna det är det bara en demo, så mina WAL-arkiv kanske inte är gigantiska siffror eftersom de är i få siffror. Jag har också listat WAL-arkiv här, som genererades från tidpunkten för säkerhetskopieringen till kraschen.

-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

Aktuellt tillstånd för WAL-arkiv och $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

Bra nu, vi har säkerhetskopian, låter INFOGA några poster i tre delar genom att notera tiden, så det kommer att hjälpa till att pausa återställningen och dessutom se WAL:s producerade från tiden för 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)

Kontrollera antalet WAL som produceras 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

Anta att olyckan inträffade vid denna tidpunkt och att du måste göra återställning med FSB + WAL-arkiv + Unarchived WAL (om några). Under återställningen vill jag pausa tre gånger för att se varje återställning av 20,00,000, 30,00,000 och 40,00,000 rader av DEMO-tabellen genom att ansluta till databasen i läsbart läge. För varje återställning av återställning behöver en omstart av återställningsklustret genom att gå till den nya tidslinjen i recovery.conf/recovery_target_time. I $FSB/postgresql.conf måste vi också ställa in hot_standby=on. Här är 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'

Låt oss börja återställa 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

Coolt, se i loggar att det har pausats och en smart TIPS som ber om att fortsätta. Här, om återställningen var tillfredsställande, kan du återuppta den genom att anropa "select pg_xlog_replay_resume();"(Du kan kolla upp det). Låt oss inte fortsätta nu, men kontrollera antalet rader som återställs genom att ansluta till servern.

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

Bra, det har nått den punkt och pausat där jag begärde. Låt oss gå ytterligare ett steg framåt för att återställa 30,00,000 rader. Ställ nu in nästa tidslinje i recovery.conf/recovery_target_time och starta om klustret.

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)

Bra..., låt oss göra det sista försöket att pausa vid 40,00,000 rader.

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)

Oj, vad hände, varför har det inte pausats och vad klagar det på?. Tänk på att om det inte finns några WAL-arkiv vid tidpunkten för recovery_target_time kommer det inte att pausa och förvänta sig eftersom det har kommit till den sista punkten och öppna databasen för READ/WRITE. I loggar, utan mycket utdrag, letade den efter filen "000000010000000000000002C" som inte är tillgänglig, eftersom klustret vid den tiden kraschade. Vissa kanske inte erkänner detta beteende men dess faktum och är vettigt när inga WAL-arkiv finns finns det ingen anledning att pausa återställningen. Om det överhuvudtaget krävs att pausa även efter inga WAL-arkiv, använd sedan standby_mode='on' (HOT_STANDBY), i den här metoden kommer det inte att komma ut ur återställningen utan vänta på WAL Archives.

Hoppas det var användbart.


  1. Service Broker-förbättringar i SQL Server 2016

  2. Uppgradering till den senaste Jira med den senaste versionen av MariaDB Server

  3. Hur man ställer in en WordPress MySQL-databas i molnet

  4. Native JSON-stöd i MYSQL 5.7:vilka är fördelarna och nackdelarna med JSON-datatyp i MYSQL?