Incidentu reaģēšana

PostgreSQL atjaunošana uz laika punktu: kā soli pa solim atsaukt kļūdainu DELETE

Kāds 14:32 izpildīja DELETE bez WHERE. Nakts rezerves kopija maksātu jums dienas datus. Atjaunošana uz laika punktu ļauj atjaunot datubāzi tādu, kāda tā bija 14:31. Lūk, kam jābūt sagatavotam iepriekš un kā atjaunošana notiek patiesībā.

· 12 min lasīšanai · AG Data komanda

PostgreSQL atjaunošana uz laika punktu (point-in-time recovery, PITR) ir tas, kas jūs izglābj, kad bojājums nāk no iekšpuses: DELETE bez WHERE, migrācija, kas izdzēsa nepareizo kolonnu, kļūda, kas kopš rīta pārraksta rindas. Replikas nepalīdz, jo tās precīzi nokopē kļūdu. Nakts pg_dump nozīmē izvēli starp dienas datu zaudēšanu un bojājuma paturēšanu. PITR ļauj atjaunot klasteri tādu, kāds tas bija minūti pirms kļūdas. Bet tikai tad, ja divas lietas bija iestatītas pirms incidenta, un tikai tad, ja atjaunošanas procedūru zināt pietiekami labi, lai to izpildītu spiediena apstākļos.

Kā tas darbojas

PostgreSQL katru izmaiņu vispirms ieraksta priekšrakstīšanas žurnālā (WAL) un tikai tad maina datu failus. PITR apvieno divas daļas, kas aprakstītas dokumentācijas nodaļā par nepārtrauktu arhivēšanu:

Lai atjaunotu, jūs atjaunojat bāzes kopiju un ļaujat PostgreSQL virs tās atskaņot arhivēto WAL, apstājoties jūsu izvēlētajā brīdī. No šīs uzbūves izriet divi ierobežojumi. Pirmkārt, tas darbojas tikai visam klasterim, nevis atsevišķai datubāzei vai tabulai. Otrkārt, pg_dump un pg_dumpall veido loģiskas izgāztuves, nevis failu sistēmas līmeņa kopijas, tāpēc PITR tās izmantot nevar vispār.

Pirms incidenta: arhivēšana un bāzes kopijas

Minimālā konfigurācija izskatās šādi. archive_command ir piemērs no dokumentācijas, kura pati to sauc par "piemēru, nevis ieteikumu":

wal_level = replica
archive_mode = on
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
archive_timeout = 60

Produkcijā daudzas komandas cp vietā izmanto tādus rīkus kā pgBackRest, WAL-G vai Barman. Tie nodrošina saspiešanu, glabāšanas politiku, paralēlismu un objektu krātuvi, bet mehānisms zem tiem ir tas pats.

Pēc tam uzraugiet arhīvu. pg_stat_archiver rāda, vai arhivēšana tiek līdzi:

SELECT archived_count, last_archived_wal, last_archived_time,
       failed_count, last_failed_wal, last_failed_time
FROM pg_stat_archiver;

Augošs failed_count vai sens last_archived_time noslogotā serverī nozīmē, ka jūsu PITR logs nav tāds, kādu domājat. Neizdevušies segmenti arī paliek pg_wal, līdz tiek arhivēti, tāpēc salūzis arhīvs galu galā var piepildīt disku; par šo situāciju rakstām mūsu ceļvedī par pilnu pg_wal disku. Ņemiet vērā, ka dokumentācija min gadījumus, kad kļūme pg_stat_archiver netiek parādīta, piemēram, ja komandu pārtrauc signāls, tāpēc brīdinājums par pēdējā arhivētā segmenta vecumu ir noderīga otrā pārbaude.

Incidenta laikā: atrodiet brīdi

Pirms pieskaraties jebkuram serverim, noskaidrojiet, kad bojājums sākās. Parastie avoti ir lietotnes žurnāli, izlaidumu laika zīmogi un PostgreSQL žurnāls (ja izteikumi tiek žurnalēti). Pierakstiet laiku ar skaidru UTC nobīdi. Dokumentācija iesaka skaitlisku nobīdi, piemēram, +02; darbojas arī pilns zonas nosaukums, piemēram, Europe/Riga, bet saīsinājumi, piemēram, EET, parasti ne.

Ja neesat pārliecināti par precīzo sekundi, izvēlieties nedaudz agrāku laiku. Uz priekšu vienmēr var aiziet tālāk; atpakaļ bez sākšanas no jauna nevar.

Atjaunojiet uz atsevišķa servera

Tā kā PITR atjauno visu klasteri, produkcijas atgriešana pagātnē nozīmē zaudēt visus likumīgos ierakstus kopš kļūdas. Parasti labāks plāns ir atjaunot uz atsevišķas mašīnas vai instances, pārbaudīt datus tur un atpakaļ nokopēt tikai skartās rindas vai tabulas. Produkcijas serveris tikmēr turpina strādāt.

Dokumentētā procedūra, pielāgota jaunam mērķa serverim:

  1. Atjaunojiet bāzes kopiju tukšā datu direktorijā, kas pieder datubāzes sistēmas lietotājam (nevis root), un pārbaudiet, vai tabulu telpu saites pg_tblspc/ norāda uz pareizajām vietām. Inkrementālu kopiju ķēdi (PostgreSQL 17 un jaunākās versijās) apvienojiet ar pg_combinebackup.
  2. Izdzēsiet visus failus, kas no kopijas palikuši pg_wal/; dokumentācija tos sauc par "visticamāk novecojušiem". Atjaunošana WAL ņems no arhīva.
  3. Konfigurējiet atjaunošanu postgresql.conf:
    restore_command = 'cp /mnt/server/archivedir/%f "%p"'
    recovery_target_time = '2026-11-02 14:31:00+02'
    recovery_target_action = 'pause'
  4. Izveidojiet tukšu failu recovery.signal datu direktorijā.
  5. Ierobežojiet piekļuvi pg_hba.conf, lai lietotnes nejauši nevarētu pieslēgties atjaunojamajam serverim.
  6. Startējiet serveri un vērojiet žurnālu. Tas prasīs failus, kuru arhīvā nav, tostarp .history failus; tas ir normāli, un restore_command tādos gadījumos vienkārši jābeidzas ar kļūdu.

Izmantojiet recovery_target_action = 'pause', kas ir arī noklusējums. Kad mērķis sasniegts, serveris pārtrauc atskaņošanu un ļauj vaicāt datus. Ja izdzēstās rindas ir vietā, beidziet atjaunošanu ar pg_wal_replay_resume(). Ja apstājāties par agru, apturiet serveri, pārceliet mērķi uz vēlāku laiku un startējiet serveri vēlreiz, lai turpinātu atjaunošanu. Pauzei vajadzīgs ieslēgts hot_standby; bez tā pause darbojas kā shutdown.

SELECT pg_is_in_recovery();
-- inspect the data, then end recovery:
SELECT pg_wal_replay_resume();

Divi iestatījumi nosaka, kur tieši atskaņošana apstājas. recovery_target_inclusive (noklusējums on) apstājas tūlīt pēc mērķa; iestatiet off, lai apstātos tieši pirms tā. Vienlaikus var iestatīt tikai vienu no mērķa iestatījumiem (recovery_target_time, _name, _xid, _lsn vai recovery_target = 'immediate'). Ja plānojat riskantas izmaiņas, pg_create_restore_point() izveido nosauktu punktu, uz kuru vēlāk var mērķēt ar recovery_target_name, un tas ir daudz vieglāk nekā minēt laika zīmogu.

Ja atjaunošanai arhivētais WAL beidzas pirms mērķa sasniegšanas, serveris apstājas ar fatālu kļūdu. Tā jūs uzzināt, ka arhīvā ir robs, un tāpēc augstāk aprakstītais monitorings ir svarīgs.

Pēc atjaunošanas: laika līnijas

Katra pabeigta arhīva atjaunošana sāk jaunu laika līniju (timeline). Laika līnijas ID ir katra WAL faila nosaukuma pirmā daļa, un neliels .history fails ieraksta, kur tā atzarojās. Tas ļauj PostgreSQL vienā arhīvā turēt veco un jauno vēsturi atsevišķi. Pēc noklusējuma atjaunošana seko jaunākajai laika līnijai arhīvā (recovery_target_timeline = 'latest'), tāpēc, ja veicat vairākas izmēģinājuma atjaunošanas, kas arhivē tajā pašā vietā, apzināti izvēlieties vajadzīgo laika līniju. Atcerieties arī, ka konfigurācijas faili, piemēram, postgresql.conf un pg_hba.conf, WAL atskaņošanā netiek atjaunoti; dublējiet tos atsevišķi.

Pārbaudiet, pirms tas vajadzīgs

PITR iestatījums, kas nekad nav atjaunots, ir cerība, nevis plāns. Regulāri veiciet atjaunošanu uz izvēlētu laika zīmogu testa serverī, nomēriet laiku un salīdziniet rezultātu ar gaidīto. Mūsu ceļvedis par rezerves kopiju un atjaunošanas testēšanu apraksta, kā to padarīt par rutīnu.

Galvenās atziņas

PostgreSQL Rezerves kopijas PITR Incidentu reaģēšana
Sadarbība ar mums

Vajag atgriezt PostgreSQL uz konkrētu brīdi?

Mēs iestatām un pārbaudām WAL arhivēšanu un atjaunošanu uz laika punktu un palīdzam atjaunot datus, kad kaut kas jau ir noticis. Pirmā reakcija uz kritiskiem incidentiem 15 minūšu laikā, 24/7.

Sazināties Vairāk no emuāra