Reproduktado ne estas sekurkopio. Aŭ ne? Jen kiel ni uzis prokrastan reproduktadon por rekuperi de hazarde forigo de ŝparvojoj.
Reproduktado ne estas rimedo por subteni datumbazojn (gitlab-ce
Kun prokrastita kopio, ni reakiris datumojn en nur 1,5 horoj. Rigardu kiel ĝi okazis.
Punkta reakiro kun PostgreSQL
PostgreSQL havas enkonstruitan funkcion, kiu restarigas la staton de datumbazo al specifa tempopunkto. Ĝi nomiĝas
Por uzi ĉi tiun funkcion por malvarma sekurkopio, ni regule faras bazan datumbazan sekurkopion kaj konservas ĝin en arkivo (GitLab-arkivoj loĝas en
Kio estas prokrastita reproduktado?
Maldiligenta reproduktado estas la apliko de ŝanĝoj de WAL kun prokrasto. Tio estas, la transakcio okazis en horo X
, sed ĝi aperos en la kopio kun prokrasto d
post unu horo X + d
.
PostgreSQL havas 2 manierojn agordi fizikan datumbazan kopion: rezerva reakiro kaj fluanta reproduktado.
Kiel agordi prokrastan reakiron de arkivo
recovery.conf
. Ekzemplo:
standby_mode = 'on'
restore_command = '/usr/bin/envdir /etc/wal-e.d/env /opt/wal-e/bin/wal-e wal-fetch -p 4 "%f" "%p"'
recovery_min_apply_delay = '8h'
recovery_target_timeline = 'latest'
Kun ĉi tiuj parametroj, ni agordis prokrastan kopion kun rezerva reakiro. Ĉi tie ĝi estas uzata restore_command
) de la arkivo, kaj ŝanĝoj estos aplikitaj post ok horoj (recovery_min_apply_delay
). La kopio rigardos por templiniaj ŝanĝoj en la arkivo, ekzemple pro grapolmalsukceso (recovery_target_timeline
).
С recovery_min_apply_delay
Vi povas agordi fluantan reproduktadon kun malfruo, sed ekzistas kelkaj faŭltoj ĉi tie, kiuj rilatas al reproduktaj fendoj, varma standby sugestoj, ktp. La WAL-arkivo permesas vin eviti ilin.
Parametro recovery_min_apply_delay
aperis nur en PostgreSQL 9.3. En antaŭaj versioj, por prokrastita reproduktado vi devas agordi la kombinaĵon pg_xlog_replay_pause(), pg_xlog_replay_resume()
) aŭ teni WAL-segmentojn en arkivo dum la tempodaŭro de la prokrasto.
Kiel PostgreSQL faras tion?
Estas interese vidi kiel PostgreSQL efektivigas maldiligentan reakiron. Ni rigardu recoveryApplyDelay(XlogReaderState)
static bool
recoveryApplyDelay(XLogReaderState *record)
{
uint8 xact_info;
TimestampTz xtime;
long secs;
int microsecs;
/* nothing to do if no delay configured */
if (recovery_min_apply_delay <= 0)
return false;
/* no delay is applied on a database not yet consistent */
if (!reachedConsistency)
return false;
/*
* Is it a COMMIT record?
*
* We deliberately choose not to delay aborts since they have no effect on
* MVCC. We already allow replay of records that don't have a timestamp,
* so there is already opportunity for issues caused by early conflicts on
* standbys.
*/
if (XLogRecGetRmid(record) != RM_XACT_ID)
return false;
xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
if (xact_info != XLOG_XACT_COMMIT &&
xact_info != XLOG_XACT_COMMIT_PREPARED)
return false;
if (!getRecordTimestamp(record, &xtime))
return false;
recoveryDelayUntilTime =
TimestampTzPlusMilliseconds(xtime, recovery_min_apply_delay);
/*
* Exit without arming the latch if it's already past time to apply this
* record
*/
TimestampDifference(GetCurrentTimestamp(), recoveryDelayUntilTime,
&secs, µsecs);
if (secs <= 0 && microsecs <= 0)
return false;
while (true)
{
// Shortened:
// Use WaitLatch until we reached recoveryDelayUntilTime
// and then
break;
}
return true;
}
La fundo estas, ke la prokrasto baziĝas sur la fizika tempo registrita en la transakcia transakcia tempostampo (xtime
). Kiel vi povas vidi, la prokrasto validas nur por transdonoj kaj ne influas aliajn enirojn - ĉiuj ŝanĝoj estas aplikataj rekte, kaj la transdono estas prokrastita, do ni vidos la ŝanĝojn nur post la agordita prokrasto.
Kiel uzi malfruan kopion por restarigi datumojn
Ni diru, ke ni havas datumbazan areton kaj kopion kun ok-hora prokrasto en produktado. Ni vidu kiel reakiri datumojn uzante ekzemplon
Kiam ni eksciis pri la problemo, ni
SELECT pg_xlog_replay_pause();
Kun paŭzo, ni havis neniun riskon, ke la kopio ripetu la peton DELETE
. Utila afero se vi bezonas tempon por eltrovi ĉion.
La punkto estas, ke la prokrastita kopio devas atingi la momenton antaŭ la peto DELETE
. Ni proksimume konis la fizikan tempon de forigo. Ni forigis recovery_min_apply_delay
kaj aldonis recovery_target_time
в recovery.conf
. Jen kiel la kopio atingas la ĝustan momenton sen prokrasto:
recovery_target_time = '2018-10-12 09:25:00+00'
Kun tempomarkoj, estas pli bone redukti la troon por ne maltrafi. Vere, ju pli granda estas la malkresko, des pli da datumoj ni perdas. Denove, se ni maltrafas la peton DELETE
, ĉio estos denove forigita kaj vi devos rekomenci (aŭ eĉ preni malvarman sekurkopion por PITR).
Ni rekomencis la prokrastita Postgres-instanco kaj la WAL-segmentoj ripetiĝis ĝis la specifita tempo. Vi povas spuri progreson en ĉi tiu etapo demandante:
SELECT
-- current location in WAL
pg_last_xlog_replay_location(),
-- current transaction timestamp (state of the replica)
pg_last_xact_replay_timestamp(),
-- current physical time
now(),
-- the amount of time still to be applied until recovery_target_time has been reached
'2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;
Se la tempomarko ne plu ŝanĝiĝas, la reakiro estas kompleta. Ago povas esti personecigita recovery_target_action
La datumbazo revenis al sia stato antaŭ tiu malfeliĉa peto. Nun vi povas, ekzemple, eksporti datumojn. Ni eksportis la forigitajn etikedajn datumojn kaj ĉiujn ligilojn al temoj kaj kunfandi petojn kaj movis ilin en la produktaddatumbazon. Se la perdoj estas grandskalaj, vi povas simple reklami la kopion kaj uzi ĝin kiel la ĉefan. Sed tiam ĉiuj ŝanĝoj post la punkto al kiu ni resaniĝis estos perditaj.
Anstataŭ tempomarkoj, estas pli bone uzi transakciajn identigilojn. Estas utile registri ĉi tiujn identigilojn, ekzemple, por DDL-deklaroj (kiel ekzemple DROP TABLE
), uzante log_statements = 'ddl'
. Se ni havus transakcian ID, ni prenus recovery_target_xid
kaj kuris ĉion malsupren al la transakcio antaŭ la peto DELETE
.
Reiri al laboro estas tre simpla: forigu ĉiujn ŝanĝojn de recovery.conf
kaj rekomencu Postgres. La kopio baldaŭ havos ok-horan prokraston denove, kaj ni estas pretaj por estontaj problemoj.
Reakiro Profitoj
Kun prokrastita kopio anstataŭ malvarma sekurkopio, vi ne devas pasigi horojn por restarigi la tutan bildon el la arkivo. Ekzemple, ni bezonas kvin horojn por akiri la tutan bazan 2 TB-rezervon. Kaj tiam vi ankoraŭ devas apliki la tutan ĉiutagan WAL por renormaliĝi al la dezirata stato (en la plej malbona kazo).
Prokrastita kopio estas pli bona ol malvarma sekurkopio en du manieroj:
- Ne necesas forigi la tutan bazan sekurkopion de la arkivo.
- Estas fiksa ok-hora fenestro de WAL-segmentoj, kiuj devas esti ripetitaj.
Ni ankaŭ konstante kontrolas por vidi ĉu eblas fari PITR de WAL, kaj ni rapide rimarkus korupton aŭ aliajn problemojn kun la WAL-arkivo monitorante la malfruon de la prokrastita kopio.
En ĉi tiu ekzemplo, ni bezonis 50 minutojn por restarigi, kio signifas, ke la rapideco estis 110 GB da WAL-datumoj hore (la arkivo ankoraŭ estis enŝaltita.
Rezultoj: kie prokrastita kopio estas utila (kaj kie ĝi ne estas)
Uzu prokrastan reproduktadon kiel unua helpo se vi hazarde perdis datumojn kaj rimarkis ĉi tiun problemon en la agordita prokrasto.
Sed memoru: reproduktado ne estas sekurkopio.
Rezervo kaj reproduktado havas malsamajn celojn. Malvarma sekurkopio utilos se vi hazarde faris DELETE
aŭ DROP TABLE
. Ni faras sekurkopion de malvarma konservado kaj restarigas la antaŭan staton de la tabelo aŭ la tuta datumbazo. Sed samtempe la peto DROP TABLE
estas preskaŭ tuj reproduktita en ĉiuj kopioj sur la funkcianta areto, do ordinara reproduktado ne helpos ĉi tie. Reproduktado mem tenas la datumbazon havebla kiam individuaj serviloj estas luitaj kaj distribuas la ŝarĝon.
Eĉ kun prokrastita kopio, ni foje vere bezonas malvarman sekurkopion en sekura loko se okazas fiasko de datumcentro, kaŝita damaĝo aŭ aliaj eventoj, kiuj ne tuj rimarkeblas. Reproduktado sole ne utilas ĉi tie.
Примечание. On
fonto: www.habr.com