Индекс на дневникаDockup / бележка от практиката
Note / database-backups-you-have-restored

Резервно копие, което никога не сте възстановявали, не е резервно копие

Непроверените резервни копия на бази данни се провалят по предвидими начини: празни dump файлове, липсващи роли, грешни флагове, липсващ ключ за криптиране. Научете как да проверите възстановяването, за да сте сигурни, че файлът, който съхранявате, действително работи.

Най-лошият момент да откриете, че дадено резервно копие не работи, е моментът, в който ви потрябва. И въпреки това най-често се случва точно това: резервните копия се конфигурират веднъж, в таблото се появява зелена отметка за осемнадесет месеца, а след това възстановяването създава празна база данни.

Тестването на възстановяване от резервно копие на база данни не е добра практика в смисъла, в който повечето добри практики са незадължителни. Резервното копие е твърдение и докато не сте възстановили поне едно, това твърдение не е проверено.

Ето по какви начини се провалят и какво всъщност трябва да проверява една верификация.

Четирите начина, по които резервното копие може незабелязано да се окаже безполезно

1. Празно е и никой не го е проверил

pg_dump, който прекъсва по средата, все пак може да създаде файл. Dump, изпълнен срещу грешно име на база данни, създава валиден, коректен и празен файл. И двата случая изглеждат като успех за всичко, което проверява само ненулев код за изход или наличието на файл.

Най-евтината проверка на света: вижте размера и го сравнете с този от вчера. Резервно копие с размер 400 байта, когато вчерашното е било 40 MB, ви казва всичко. Резервно копие, което е 400 байта от шест месеца, ви го казва през цялото време.

2. Съдържа данни, но не и нещата около тях

pg_dump на една база данни не включва роли и не включва други бази данни. Възстановете го на нов сървър и таблиците ще се появят, но всеки GRANT ще сочи към несъществуваща роля. Приложението ви ще се свърже и ще получи отказ за права за всичко.

С разширенията е същото. Ако схемата ви зависи от pgcrypto или uuid-ossp, а целевата система не ги разполага, възстановяването ще се провали по средата и ще ви остави с част от таблиците.

3. Флаговете са били грешни за възстановяването, което ви е необходимо

pg_dump създава различни неща в зависимост от формата, а грешката обикновено се открива под напрежение:

  • Plain SQL се възстановява с psql и е четим от хора. Не може да се възстановява избирателно и е бавен при големи бази данни.
  • Custom format (-Fc) се възстановява с pg_restore, поддържа паралелизъм и избирателно възстановяване и е форматът, който ви трябва за всичко с по-значителен размер.

Да направите резервно копие в plain format, защото така е било в урока, и след това по време на инцидент да откриете, че не можете да възстановите една таблица, е конкретен и напълно предотвратим вид лош ден.

4. Не можете да го декриптирате

Ако резервните копия са криптирани — а би трябвало да бъдат — ключът е част от резервното копие. Ключ, който се намира само на изгубената машина или само в environment variable на спрялата услуга, е ключ, с който не разполагате, когато ви потрябва.

Как изглежда една реална проверка

Тестът не е „съществува ли файлът“. Възстановете го някъде другаде и му задайте въпрос.

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

Стъпка 2 е целият смисъл. Възстановяване, което завършва без грешка, все още не ви казва нищо за това дали данните са там. Броят на редовете и проверката за актуалност го показват.

Три неща, които си струва да проверите:

  • Броят на редовете е в правилния порядък. Не е нужно да е точен — данните се променят — но таблица, която е имала 200 000 реда, а сега има 12, означава провал.
  • Най-новият запис е скорошен. Ако най-новата поръчка в „нощното“ ви резервно копие е от март, задачата за архивиране е спряла през март.
  • Приложението действително може да се свърже. Насочете staging инстанция към възстановената база данни и заредете една страница.

Правете го по график, а не когато се сетите

Реалистичният график е веднъж месечно, автоматизирано, като резултатът се изпраща на място, което ще забележите. Напомняне в календара с текст „тествай резервните копия“ е напомняне, което ще отложите.

Това, което прави процеса устойчив, е да направите грешката видима: ако заявката за проверка върне по-малко редове от даден праг, това трябва да изпрати page съобщение до някого по същия начин, по който би го направила production грешка. Система за резервни копия, която се проваля безшумно, не се различава от липсата на система за резервни копия — поне докато не се окаже нужна.

Как Dockup се справя с това

Три решения, всяко насочено към конкретен от описаните по-горе проблеми.

Резервните копия се съхраняват на друго място. Резервно копие на същия диск като базата данни не е резервно копие — то е копие, което ще загине заедно с диска. Dockup предава резервните копия на бази данни директно към object storage, докато ги създава, така че файлът никога не зависи от хоста, на който е създаден.

Те са криптирани, а ключът не е на машината. Резервните копия се криптират с AES-256-GCM, докато се предават. Важното за възстановяването е, че ключът се съхранява от платформата, вместо да се намира в environment-а на услугата, чието резервно копие се създава.

Резервно копие, което не е създало нищо, не се записва като резервно копие. Това директно решава проблема с празния файл: ако dump процесът завърши с ненулев код или създаде нула байта, качването се изтрива, а резервното копие се записва като неуспешно. Няма да получите списък със зелени записи, сред които един е файл от 400 байта.

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

Размерите в този списък са най-евтината health check проверка, с която разполагате. Следете тенденцията им.

Неудобният въпрос

Ако production базата ви данни бъде унищожена през следващите десет минути, колко време ще ви е необходимо, за да я възстановите, и колко данни ще сте загубили?

Ако не можете да отговорите и с двете числа, нямате стратегия за резервни копия — имате файлове с резервни копия. Разликата е изцяло в това дали някой някога е извършвал възстановяването.

Често задавани въпроси

Колко често трябва да тествам възстановяване? Веднъж месечно е разумна отправна точка, като процесът трябва да е автоматизиран, а не ръчен. Важното е грешката да е видима, не графикът да е агресивен.

Защо възстановяването ми завърши, но не създаде данни? Обикновено dump-ът е създаден срещу грешна база данни или е прекъснал по средата, докато файлът все още се е записвал. Сравнявайте размерите на резервните копия във времето — празният dump е очевиден в тенденцията на размера и невидим в колоната за статуса.

Трябва ли резервните копия да бъдат криптирани? Да, а ключът трябва да се съхранява на място, което ще оцелее при загубата на машината. Криптирано резервно копие, чийто ключ е бил на изгубения сървър, не може да бъде възстановено.

Snapshot същото ли е като резервно копие? Не. Snapshot на volume заснема диска, включително състоянието, в което се е намирала базата данни в този момент. Логическият dump е консистентен по замисъл. Повечето екипи искат и двете, заради различните видове повреди.