Indexul jurnaluluiDockup / notă de teren
Note / database-backups-you-have-restored

Un backup pe care nu l-ai restaurat niciodată nu este un backup

Backup-urile de baze de date netestate eșuează în moduri previzibile: dump-uri goale, roluri lipsă, flag-uri greșite, nicio cheie de criptare. Află cum să verifici o restaurare, astfel încât fișierul pe care îl păstrezi să fie unul funcțional.

Cel mai prost moment în care poți descoperi că un backup nu funcționează este chiar momentul în care ai nevoie de el. Și totuși, acesta este scenariul covârșitor de frecvent: backup-uri configurate o singură dată, o bifă verde într-un dashboard timp de optsprezece luni, iar apoi o restaurare care produce o bază de date goală.

Testarea restaurării unui backup de bază de date nu este o bună practică în sensul în care majoritatea bunelor practici sunt opționale. Un backup este o afirmație, iar până când nu ai restaurat unul, este o afirmație neverificată.

Iată cum eșuează și ce trebuie să verifice, de fapt, o validare.

Cele patru moduri în care un backup devine inutil fără ca nimeni să observe

1. Este gol și nimeni nu s-a uitat

Un pg_dump care eșuează la jumătate poate totuși să producă un fișier. Un dump executat pentru numele greșit al bazei de date produce un fișier valid, corect și gol. Ambele arată ca un succes pentru orice verificare care caută un exit code diferit de zero sau existența unui fișier.

Cea mai ieftină verificare din lume: uită-te la dimensiune și compar-o cu cea de ieri. Un backup de 400 de bytes, când cel de ieri avea 40 MB, ți-a spus tot ce trebuia să știi. Un backup care are 400 de bytes de șase luni îți spune asta de atunci.

2. Conține date, dar nu și lucrurile din jurul lor

pg_dump pentru o singură bază de date nu include roluri și nici alte baze de date. Restaurează-l pe un server nou, iar tabelele vor apărea, în timp ce fiecare GRANT se va referi la un rol care nu există. Aplicația ta se conectează și primește „permission denied” pentru orice.

Extensiile urmează aceeași poveste. Dacă schema ta depinde de pgcrypto sau uuid-ossp, iar ținta nu le are, restaurarea eșuează la jumătate, lăsându-te cu câteva tabele.

3. Flag-urile au fost greșite pentru restaurarea de care ai nevoie

pg_dump produce lucruri diferite în funcție de format, iar greșeala este de obicei descoperită sub presiune:

  • Plain SQL se restaurează cu psql și poate fi citit de oameni. Nu poate fi restaurat selectiv și este lent pentru bazele de date mari.
  • Custom format (-Fc) se restaurează cu pg_restore, acceptă paralelism și restaurare selectivă și este ceea ce îți dorești pentru orice bază de date de dimensiuni considerabile.

Să faci backup în format plain pentru că așa proceda tutorialul, iar apoi să descoperi în timpul unui incident că nu poți restaura un singur tabel este un tip de zi proastă specific și ușor de evitat.

4. Nu îl poți decripta

Dacă backup-urile sunt criptate — și ar trebui să fie — atunci cheia face parte din backup. O cheie care există doar pe mașina pierdută sau doar într-o variabilă de mediu a serviciului indisponibil este o cheie pe care nu o ai atunci când contează.

Cum arată o verificare reală

Testul nu este „există fișierul?”. Este să îl restaurezi în altă parte și să îi adresezi o întrebare.

# 1. Restore into a scratch database, not the live one
createdb verify_$(date +%Y%m%d)
pg_restore -d verify_$(date +%Y%m%d) --no-owner --no-privileges latest.dump

# 2. Ask it something only real data can answer
psql -d verify_$(date +%Y%m%d) -c "
  select
    (select count(*) from users)            as users,
    (select count(*) from orders)           as orders,
    (select max(created_at) from orders)    as newest_order;
"

# 3. Drop it
dropdb verify_$(date +%Y%m%d)

Pasul 2 este esența întregului proces. O restaurare care se finalizează fără erori nu îți spune totuși nimic despre existența datelor. Numărul de rânduri și verificarea caracterului recent al datelor îți spun.

Trei lucruri care merită verificate explicit:

  • Numărul de rânduri este în ordinul de mărime corect. Nu trebuie să fie exact — datele se schimbă — dar un tabel care avea 200.000 de rânduri și acum are 12 indică un eșec.
  • Cea mai recentă înregistrare este recentă. Dacă cea mai recentă comandă din backup-ul tău „zilnic” este din martie, jobul de backup s-a oprit în martie.
  • Aplicația se poate conecta efectiv. Direcționează o instanță de staging către baza de date restaurată și încarcă o pagină.

Fă asta după un program, nu când îți amintești

Frecvența realistă este lunară, automatizată, cu rezultatul într-un loc unde îl vei observa. Un reminder în calendar pentru „testarea backup-urilor” este un reminder pe care îl vei amâna.

Ceea ce face procesul să funcționeze este să faci eșecul imposibil de ignorat: dacă interogarea de verificare returnează mai puține rânduri decât un prag, acest lucru ar trebui să trimită o alertă cuiva, exact ca o eroare de producție. Un sistem de backup care eșuează în tăcere nu se deosebește de absența unui sistem de backup — cel puțin până când devine important.

Cum gestionează Dockup acest lucru

Trei decizii, fiecare vizând un eșec specific de mai sus.

Backup-urile ajung în altă parte. Un backup pe același disc cu baza de date nu este un backup — este o copie care dispare odată cu discul. Dockup transmite backup-urile bazelor de date direct în object storage pe măsură ce sunt produse, astfel încât fișierul să nu depindă niciodată de hostul care l-a creat.

Sunt criptate, iar cheia nu se află pe mașină. Backup-urile sunt criptate cu AES-256-GCM pe măsură ce sunt transmise. Pentru recuperare, partea relevantă este că cheia este păstrată de platformă, nu în mediul serviciului pentru care se face backup.

Un backup care nu a produs nimic nu este înregistrat ca backup. Aceasta este decizia care tratează direct problema fișierului gol: dacă dump-ul se încheie cu un exit code diferit de zero sau produce zero bytes, upload-ul este șters, iar backup-ul este înregistrat ca eșuat. Nu ajungi cu o listă de intrări verzi în care una este un fișier de 400 de bytes.

dockup db backup my-project/main-db --json     # take one now
dockup db backups my-project/main-db --json    # list them with sizes

Dimensiunile din acea listă sunt cea mai ieftină verificare de sănătate pe care o ai. Urmărește evoluția lor.

Întrebarea incomodă

Dacă baza ta de date de producție ar fi distrusă în următoarele zece minute, cât timp ți-ar lua să o readuci online și cât ai pierde?

Dacă nu poți răspunde cu ambele numere, nu ai o strategie de backup — ai fișiere de backup. Diferența constă în întregime în faptul că a făcut cineva vreodată restaurarea.

Întrebări frecvente

Cât de des ar trebui să testez o restaurare? Lunar este un interval implicit rezonabil, automatizat, nu manual. Partea importantă este ca un eșec să fie imposibil de ignorat, nu ca frecvența să fie agresivă.

De ce s-a finalizat restaurarea, dar nu a produs date? De obicei, dump-ul a fost făcut pentru baza de date greșită sau a eșuat la jumătate, continuând totuși să scrie un fișier. Compară dimensiunile backup-urilor în timp — un dump gol este evident într-o evoluție a dimensiunii și invizibil într-o coloană de status.

Backup-urile ar trebui criptate? Da, iar cheia trebuie să se afle într-un loc care supraviețuiește pierderii mașinii. Un backup criptat a cărui cheie se afla pe serverul pierdut nu poate fi recuperat.

Este un snapshot același lucru cu un backup? Nu. Un snapshot al unui volum capturează discul, inclusiv starea în care se afla baza de date în acel moment. Un dump logic este consistent prin construcție. Majoritatea echipelor le vor pe amândouă, pentru tipuri diferite de eșecuri.