Випуск і експлуатація
Відкат і відновлення: повернути систему, не втративши дані вдруге
Кнопка «повернути попередню версію» може знову показати сторінку, але не поверне видалені рядки, не скасує списання коштів і не змінить формат…
Кнопка «повернути попередню версію» може знову показати сторінку, але не поверне видалені рядки, не скасує списання коштів і не змінить формат повідомлень, уже записаних у чергу. Відновлення починається з точного питання: який стан пошкоджено, який стан потрібен і які зміни після обраної точки треба зберегти або відтворити?
У цьому розділі відкат (rollback) означає повернення певної частини системи до попередньої версії чи конфігурації. Відновлення — повернення сервісу й даних до узгодженого робочого стану. Це різні операції: можна відкотити програмний артефакт, але лишити базу, платежі та чергу такими, як вони є. Так само можна відновити копію бази, але ще не мати готової системи для користувачів.
Після розділу читач може:
- розрізнити відкат випуску, скасування зміни в системі керування версіями, відновлення копії, перемикання на репліку й виправлення рухом уперед (forward fix);
- визначити, які частини системи треба відновити разом: артефакт, конфігурацію, схему, дані, черги, зовнішні ефекти й контроль доступу;
- оцінити допустиму втрату даних і час простою через цільову точку відновлення (Recovery Point Objective, RPO) та цільовий час відновлення (Recovery Time Objective, RTO);
- побудувати план на ізольованій копії, перевірити інваріанти та узгодити нові записи до перемикання;
- обрати відкат чи виправлення за тим, що зменшує шкоду й не руйнує єдину придатну копію даних.
Навчальні сценарії вигадані. Розділ не є інструкцією для відновлення конкретної виробничої бази: точні кроки залежать від рушія даних, версій, постачальника, застосунку й повноважень команди. Повний порядок реагування на інцидент, комунікацію та чергування розглянуто в розділі 62; оформлення покрокових runbook — у розділі 63.
60.1. Що саме означає «повернути назад»
У розмові слово «rollback» часто накриває кілька операцій із різною семантикою:
| Операція | Що повертає або змінює | Чого сама по собі не робить |
|---|---|---|
| Відкат випуску | Запускає раніше зібраний артефакт або спрямовує трафік на попередній пул. | Не відкочує схему, рядки, кеші, черги, зовнішні запити чи дії користувачів. |
| Скасувальний commit у системі керування версіями | Додає нову зміну, що обертає вибраний diff у репозиторії. | Не змінює вже запущені екземпляри, базу або опубліковані артефакти, доки нову зміну окремо не розгорнуто. |
| Перемикання прапорця чи конфігурації | Вимикає поведінку або змінює параметр виконання, якщо всі компоненти читають його та підтримують повернене значення. | Не скасовує вже завершені операції й не гарантує, що кеш чи довготривалий процес застосував нове значення. |
| Відновлення копії | Створює стан із резервної копії, знімка або журналу до визначеної точки. | Не виявляє автоматично пропущені нові записи й не відтворює зовнішні ефекти після точки. |
| Перемикання на репліку або резервний вузол (failover) | Переводить роботу на інший екземпляр даних чи обчислень. | Не доводить, що копія актуальна, здорова або не містить ту саму логічну помилку. |
| Виправлення рухом уперед (forward fix) | Випускає зміну, яка виправляє поточний стан без повернення до старого випуску. | Не повертає автоматично дані, вже перетворені помилковою логікою. |
Уявіть систему як кілька пов’язаних, але незалежно змінюваних шарів: програмний артефакт; конфігурація, секрети й правила доступу; структура бази та її рядки; черги, кеші й пошукові індекси; об’єктне сховище; а також зовнішні системи — платіжний сервіс, постачальник пошти чи партнерський API (Application Programming Interface — програмний інтерфейс застосунку). Щоб повернутися в робочий стан, треба знати не тільки версію коду, а й узгоджені версії цих залежностей.
Відкат — це не машина часу. Після розгортання могли надійти нові замовлення, бути надіслані листи, змінитися баланс або з’явитися нові повідомлення у черзі. Повернення всієї бази до вчорашнього знімка прибере і корисні зміни після нього. Якщо стара версія схеми не читає нове поле, бездумний відкат коду також може перетворити часткову помилку на повну недоступність.
Розділ 52 про міграції вже описав сумісність старого й нового коду зі схемою під час зміни. Тут інше питання: що робити, коли зміна вже зашкодила? Наявність сумісної схеми може зробити відкат безпечним; видалення чи перетворення даних може зробити його непридатним.
60.2. Знайдіть межу помилки й точку, з якою порівнюєте
Перед вибором засобу запишіть чотири факти:
- Яка поведінка зламана? Наприклад, новий код повертає помилку пошуку, а не правильний результат.
- Який стан уже змінився? Перевірте не лише основну таблицю, а й похідні записи, черги, кеші, журнали та інтеграції.
- Коли почалося пошкодження або некоректна поведінка? Невідомий початок означає, що точка відновлення теж невизначена.
- Яка копія або версія доведено придатна? Перевірте ідентифікатор артефакту, сумісність схеми, цілісність копії та доступність усіх залежностей.
«Останній відомо справний стан» — це не просто попередній номер версії. Він може складатися з хешу артефакту, конфігурації, параметрів інфраструктури, версії схеми, точки даних, позиції журналу, версій повідомлень і потрібних секретів. Деякі з цих частин можна повернути, інші — лише перечитати або створити знову. Вкажіть, хто підтверджує кожну частину та яким спостереженням це підтверджується.
Не плутайте симптом із причиною. Якщо помилку спричиняє конфігурація, повернення коду може нічого не змінити. Якщо база правильна, але пошуковий індекс застарілий, відновлення бази може бути зайвим і навіть відкотити корисні записи. На цьому етапі потрібні достатні докази для вибору дії; детальний процес координації людей і комунікації належить до розділу реагування на інциденти.
60.3. Відкат випуску має умови сумісності
Найпростіший відкат — повернути попередній артефакт або конфігурацію. Він часто доречний, коли помилка в поведінці нової версії, а спільний стан не зазнав несумісної зміни. Повну модель співіснування версій розглянуто в главі 59. Перевірте перед ним:
- Чи стара версія запускається на поточній схемі й чи не очікує відсутніх стовпців або старих обмежень?
- Чи розуміють старі читачі новий формат повідомлень у черзі, кеші й файлах?
- Чи не змінилися формат сесії, токенів, ключів шифрування або адреси залежного сервісу?
- Чи зупиняються вже активні довгі запити та фонові завдання без повторного виконання зовнішньої операції?
- Чи можна відключити нову поведінку прапорцем, не зупиняючи незавершене оформлення платежу, імпорт або бронювання?
Зміна в репозиторії та зміна в живій системі — різні кроки. Скасувальний commit може підготувати випуск, але не робить його активним, поки відповідна доставка не завершиться. Так само відкат контейнерного тегу не повертає сторонню конфігурацію, якщо вона оновлювалася окремо. Використовуйте незмінний ідентифікатор артефакту та відомий попередній маніфест, а не тег на кшталт latest, зміст якого міг змінитися.
Старий артефакт може бути не безпечним: у ньому може бути відома вразливість, закінчений сертифікат або контракт, який уже не підтримується. Порівняйте шкоду від нової помилки зі шкодою від повернення старого стану. Коли старий код не сумісний із поточною схемою, часто безпечніше вимкнути лише проблемну поведінку чи випустити мале виправлення вперед, аніж примусово повертати всю програму.
60.4. Копії, журнали, репліки й перемикання — різні гарантії
Резервна копія — це збережене представлення стану на певному зрізі. Це може бути логічний експорт таблиць, фізична копія сховища або знімок тома. Вони мають різні властивості: логічну копію зручніше переносити чи вибірково імпортувати, а фізичну інколи швидше відновити як узгоджений екземпляр. Не робіть висновків про можливість точкового відновлення, не звіривши формат і процедуру саме з документацією вашої бази.
У PostgreSQL 18 безперервне архівування спирається на базову копію кластера та архів журналу попереднього запису (Write-Ahead Log, WAL). Відновлення до точки в часі (point-in-time recovery, PITR) застосовує записи з WAL до потрібного моменту; копії журналів мають повністю покривати шлях від обраної базової копії. Документація окремо попереджає, що неповний набір журналів не дасть завершити відновлення, а інкрементальна копія потребує всіх копій, від яких вона залежить. Таке відновлення охоплює цілий кластер, а не довільно вибрану таблицю. Крім того, WAL не повертає зміни до postgresql.conf, pg_hba.conf і pg_ident.conf: ці файли треба зберігати окремо. Це механіка PostgreSQL 18, а не обіцянка для будь-якого сховища. (PostgreSQL 18: безперервне архівування й PITR, переглянуто 10.10.2026.)
Реплікація підтримує окремий екземпляр для доступності, читання або перемикання. Вона часто швидко передає зміни — і тому може швидко передати випадкове видалення, хибне оновлення чи логічну помилку. Репліка, яка без запізнення повторює кожну транзакцію, корисна проти відмови вузла, але сама по собі не є незалежною історичною копією. Відкладена репліка дає коротке вікно, щоб зупинити застосування помилкового запису, але це не замінює довготривалу копію й також потребує перевірки.
Failover переводить навантаження на резервний вузол. Якщо причина — аварія вузла, це може відновити обслуговування. Якщо причина — хибний запис, погана конфігурація, скомпрометований доступ або пошкоджений формат даних, перемикання може перенести шкоду на резервний вузол чи збільшити її. Перед перемиканням перевірте відставання репліки та точку, до якої вона застосувала дані; після нього зафіксуйте, який вузол тепер приймає записи.
Керований сервіс теж має власні обмеження. Наприклад, Amazon Relational Database Service (Amazon RDS) створює новий екземпляр при відновленні до точки в часі, а вихідний екземпляр не змінюється. Це дає можливість перевірити відновлену копію перед зміною клієнтського маршруту. Сервіс обмежує вибір точки доступним періодом зберігання копій, а деякі дії чи рушії мають окремі умови. Звіряйте конкретний рушій і параметри, а не переносіть поведінку RDS на інший продукт. (Документація Amazon RDS: відновлення до заданої точки в часі, переглянуто 24.09.2026.)
Кеші та індекси часто можна перебудувати з джерела істини, але лише якщо воно правильне й відоме. Черга містить незавершену роботу, тому її не можна просто очистити, не з’ясувавши наслідки для клієнтів. Об’єктне сховище й файли можуть мати окремий графік копіювання. Для кожного шару запитайте: чи можна його безпечно відтворити, чи містить він унікальне джерело істини, і чи узгоджена його версія з обраною точкою бази?
60.5. RPO та RTO описують прийнятну втрату й простій
Recovery Point Objective (RPO) — максимальний часовий проміжок змін перед інцидентом, який бізнес готовий втратити; він задає, наскільки новою має бути остання допустима точка відновлення. Recovery Time Objective (RTO) — максимальний прийнятний проміжок від переривання до відновлення потрібної послуги. Google описує ці цілі як «скільки часу до відновлення» та «скільки даних можна втратити»; конкретні значення різняться за критичністю продукту й бізнес-потребами. (Google Cloud: архітектура відновлення після аварій інфраструктури, переглянуто 10.05.2024.)
Цілі перетворюють технічний вибір на продуктове рішення. Для особистого чернеткового каталогу втрата кількох хвилин може бути прийнятною; для обліку платежів навіть один неузгоджений запис може вимагати ручної звірки. Коротше RTO зазвичай потребує більше підготовленої інфраструктури й перевірених переходів; менше RPO — частішого збереження змін, довшого журналу або синхроннішого передавання. Це впливає на складність, ціну та операційне навантаження. Універсального значення для всіх систем немає.
Порівнюйте цілі з виміряними результатами відновлення, а не лише з розкладом копіювання. RTO охоплює виявлення правильної копії, її створення, перевірку, відтворення нових корисних змін, зміну маршруту, перевірку роботи та повернення залежних сервісів. «Копія щовечора» не доводить ані щоденного RPO, ані RTO в межах доби: невідомі тривалість відновлення, цілісність файлу, потрібні ключі й актуальність конфігурації.
60.6. Послідовність безпечного відновлення
Це не універсальний runbook, а порядок міркування, який треба перетворити на перевірені для своєї системи кроки:
- Збережіть доказ і стан. Зафіксуйте час, ідентифікатори релізу, конфігурації, точки бази й журналів, сигнали, логи та вже виконані дії. Де можливо, збережіть пошкоджену копію окремо. Не знищуйте її, поки не вирішено, що вона не потрібна для розслідування чи вилучення корисних нових даних.
- Зупиніть подальше псування. Припиніть саме ту зміну, що продовжує шкоду: наприклад, записи нової логіки, повторні імпорти або фонове завдання. Не вимикайте навмання всю систему, якщо це призведе до дублів, втрати платежів чи зростання черги. Вкажіть, які операції ще дозволено завершити.
- Оберіть цільовий стан. Запишіть артефакт, параметри, схему, копію та точку журналу. Перевірте джерело, часовий пояс, ідентифікатор бази, повноту ланцюга журналів і відповідність версії рушія. «Вчора о 02:00» без точного джерела й підтвердженої часової шкали — недостатній план.
- Створіть копію для перевірки окремо. Використайте ізольоване середовище, забороніть звичайним клієнтам до нього під’єднуватися, обмежте вихідні інтеграції та вимкніть автоматичні листи, вебхуки чи платежі. Не перемикайте production на ціль тільки тому, що процес відновлення завершився без помилки.
- Перевірте узгодженість. Перевірте, що базові інваріанти мають сенс для продукту: ключі посилаються на наявні рядки; суми відповідають обліку; кількість зарезервованих місць не перевищує доступну; відсутні дублікати унікальних ідентифікаторів; контрольні суми або підсумки узгоджуються з незалежним джерелом. Технічний статус «сервер запустився» — не перевірка бізнес-стану.
- Складіть реєстр змін після точки. Зіставте журнали транзакцій, ідентифікатори запитів, бізнес-події, інвойси, підтвердження платіжного провайдера, файли й листи. Розрізніть: зміни, які треба відтворити; записи, вже включені до відновленої копії; дублікати; непідтверджені зовнішні дії; незворотні операції.
- Узгодьте дані до повернення записів. Зупиніть або обмежте конкурентні автори, визначте порядок імпорту й дедуплікації, перевірте повторне виконання на копії. Якщо джерело істини не дозволяє безпечно звести дві гілки записів, не вгадуйте: залиште систему на контрольованому режимі, доки власник даних не визначить рішення.
- Перемкніть джерело запису один раз. Перевірте назву й адресу цілі, схему, доступи та записуваний вузол безпосередньо перед дією. Після перемикання виконайте малий контрольний бізнес-сценарій, перевірте фактичні записи й лише потім поступово відновлюйте звичайне навантаження, якщо архітектура дозволяє це робити.
- Звірте наслідки й збережіть копію. Перевірте журнали помилок, черги, лічильники, цілісність і повторні ефекти. Зафіксуйте, яку втрату прийнято, які записи відтворено й хто це погодив. Зберігайте попередній екземпляр і докази достатньо довго, щоб мати змогу виправити хибний вибір точки.
Документація Google Cloud радить оцінювати перевірку відновлення щонайменше за цілісністю даних, RPO і RTO, а також перевіряти застосунок і критичні залежності на відновлених даних у непродукційному середовищі. Вона підкреслює: успіх копіювання ще не означає, що весь застосунок працює. У книзі Google Site Reliability Engineering (SRE — інженерія надійності сайтів) команда також застерігає, що реплікація не захищає від багатьох джерел втрати даних і що стратегію копій слід оцінювати за здатністю відновити потрібний стан. (Google Cloud Well-Architected: перевірка відновлення після втрати даних, переглянуто 30.12.2024; Google SRE: Data Integrity, 2016.) Це не вимога застосовувати продукти Google, а критерії доказу для будь-якого плану відновлення.
Для фізичних резервних копій PostgreSQL 18 має утиліту pg_verifybackup: вона перевіряє маніфест, склад файлів, контрольні суми й доступні їй журнали для копії pg_basebackup. Проте сама документація прямо каже, що ця перевірка не охоплює всіх умов, які перевірить сервер під час відновлення, і все одно радить тестове відновлення та перевірку вмісту. Отже, успішна автоматична перевірка є корисною частиною доказу, а не завершальним доказом працездатності. (PostgreSQL 18: pg_verifybackup, переглянуто 24.09.2026.)
60.7. Код, база й зовнішні ефекти можуть вимагати різних рішень
Після зміни розгляньте кілька рішень окремо. Їх можна поєднати, якщо для кожного визначено стан і власника:
| Ситуація | Ймовірний перший варіант | Перевірка, без якої варіант ризикований |
|---|---|---|
| Новий артефакт помиляється, стан не змінено | Відкат до попереднього артефакту або вимкнення функції. | Сумісність старого коду з поточною схемою, кешем і повідомленнями. |
| Конфігурація зламала поведінку | Повернення попереднього значення або вузька зміна параметра. | Чи не потрібна зміна лише для однієї групи; які процеси вже перечитали конфігурацію. |
| Некоректні дані ще обмежені, причина зрозуміла | Виправлення даних вперед із перевіреним правилом; можливо, випуск коду. | Чи збережені первинні значення й чи можна правильно відрізнити пошкоджені рядки. |
| Значна частина даних зіпсована до відомої точки | Відновлення копії до цієї точки з окремою звіркою нових записів. | Чи повна копія та її журнал, чи можна повернути зміни після точки, чи є план зовнішніх ефектів. |
| Невідомо, чи репліка містить помилку | Зупинити автоматичне перемикання, порівняти стан і час останнього запису. | Реплікація сама не відокремлює коректні транзакції від помилкових. |
| Списано кошти, надіслано листи, опубліковано події | Окреме відновлення внутрішніх даних плюс компенсаційна дія та узгоджена комунікація. | Повторний ефект може бути небажаним; потрібні квитанції та ідентифікатори зовнішньої системи. |
Відкат виправданий, коли попередній код сумісний із поточним станом і швидко зупиняє шкоду. Виправлення вперед краще підходить, коли попередня версія не може прочитати вже змінені дані або коли помилка локальна й дані можна перевірено відкоригувати. Відновлення з копії потрібне, коли джерело істини пошкоджене настільки, що окреме виправлення ненадійне; але воно відкриває окрему задачу — повернути правильні записи, створені після точки.
Зовнішню дію не можна вважати «скасованою» лише тому, що програма повернулася до старої версії. Для повернення платежу потрібна окрема операція повернення; надісланий лист не можна відкликати; доставлене партнеру повідомлення вже могло запустити його робочий процес. Ідемпотентний ключ, журнал намірів і квитанція допомагають виявити повтори, але не повертають час назад. Перед компенсацією з’ясуйте, чи зовнішня система справді прийняла оригінальну операцію.
60.8. Приклад: каталог повертає помилку, дані лишилися правильними
Вигаданий приклад. Сервіс каталогу товарів отримав випуск, що змінив логіку читання індексу. Пошук почав завершуватися помилкою, але команди запису товарів не змінювалися, перевірка основної таблиці показує попередні ціни й описи, а черга переіндексації не містить незвичних завдань. Старий вебартефакт використовує ту саму схему й формат індексу.
Власник сервісу зупиняє розширення випуску й звіряє точні артефакти та конфігурацію. Оскільки немає ознаки пошкодження джерела даних, команда може відкотити вебкод або вимкнути нову гілку пошуку, лишивши базу на поточному стані. Перед поверненням трафіку вона перевіряє не тільки код відповіді 200 протоколу передавання гіпертексту (Hypertext Transfer Protocol, HTTP): вибіркові запити з різними фільтрами мають знаходити очікувані товари, а запис нового товару — залишатися видимим у пошуку.
Якщо проблема тільки в похідному індексі, команді може знадобитися його перебудова з таблиць після усунення несправного коду. Відновлення всієї бази до старого знімка було б невиправданим: воно відкинуло б правильні зміни товарів і не гарантувало б виправлення самої логіки запиту. Тут «відкотити реліз» і «відновити дані» — різні рішення з різною ціною.
60.9. Приклад: помилкова ціна вже потрапила в замовлення й оплату
Вигаданий приклад. Нова версія каталогу неправильно застосувала правило округлення та змінила ціну 240 товарів. Протягом двадцяти хвилин клієнти оформили 40 замовлень. Зовнішній платіжний сервіс підтвердив списання для частини з них; для кількох запитів підтвердження ще не надійшло.
Команда вимикає помилковий розрахунок нових цін і зупиняє масове оновлення. Відкат артефакту може повернути стару формулу для наступних переглядів, але замовлення вже мають зафіксовану суму. Якщо ж відновити базу до моменту перед випуском, з неї можуть зникнути самі замовлення, підтвердження платежів і статуси, створені згодом. Платіжний провайдер не скасує списання лише тому, що внутрішній запис зник.
Власник фінансових даних зіставляє аудит змін цін, версію правила, незмінений журнал замовлень, ідентифікатори запитів, платіжні квитанції та відповіді вебхуків. Він позначає кожне замовлення як: не надіслане провайдеру; підтверджене; відхилене; або з невідомим результатом. Для невідомого результату команда спершу запитує статус за зовнішнім ідентифікатором — повторний платіжний запит може створити друге списання.
Потім команда порівнює два варіанти. Якщо множину пошкоджених цін можна точно визначити з журналу подій і первинних значень, контрольований виправний перерахунок уперед може зберегти 40 замовлень та інші нові записи. Якщо пошкодження поширилося на значну кількість рядків і початок точно відомий, резервну копію можна відновити в окрему базу, витягти звідти правильні ціни та зіставити з актуальними замовленнями. Це ще не рішення замінити всю поточну базу.
У всіх варіантах треба прийняти окреме рішення для вже оплачених замовлень: виконати за показаною ціною, повідомити про зміну, повернути різницю чи повну суму згідно з політикою магазину та застосовним процесом обслуговування. Команда не повторює списання автоматично, а записує квитанцію або результат компенсації до журналу. Критерій успіху — узгоджені ціни, замовлення й фактичні платежі, а не лише сторінка, що знову відкривається.
60.10. Приклад: файл копії є, але відновлення ще не доведене
Вигаданий приклад. Команда знаходить нічну базову копію за 01:00. У сховищі також видно частину файлів WAL, а панель роботи резервного копіювання показує «успішно». У 11:40 застосунок почав помилково видаляти записи. Власник бази хоче відновити стан за 11:35.
Під час перевірки виявляється, що каталог WAL має пропуск у сегментах між 10:50 і 11:10 і іншого повного джерела цих сегментів команда не знайшла. Крім того, конфігурація відновлення, облікові дані доступу й шлях до секретів зберігаються поза WAL; потрібні параметри та ключ ще не підтверджено. У PostgreSQL журнали даних не повертають вручну змінені файли конфігурації. Отже, наявність базового файла доводить лише те, що якийсь файл збережено. Вона не доводить, що його можна повністю відтворити до 11:35 та використати разом із сумісною конфігурацією й доступами.
Команда не замінює основну базу здогадом. Вона зберігає поточні файли й метадані, перевіряє ланцюг копій, журналів, ключів і версій, а потім пробує відновити ізольований екземпляр до найпізнішої точки, яку реально покривають безперервні записи. Якщо журнал після 10:50 відсутній, PostgreSQL не може магічно відтворити історію до 11:35 з однієї базової копії; доведена точка наразі може бути не новішою за 10:50. Доведеться оцінити інші копії, джерела подій та ціну втрати приблизно 50 хвилин змін або вибрати окреме виправлення.
Навіть коли сервер піднявся, власник звіряє схему, ключі, облікові записи застосунку, контрольні підсумки та критичну дію в непід’єднаному до реальних клієнтів середовищі. Тільки після цього можна говорити про перевірену точку. Резервна копія стала кандидатом для відновлення; доказом придатності стали повний шлях відновлення, конфігурація й успішна перевірка даних і поведінки.
60.11. Реальний випадок: у GitLab не спрацювали кілька шарів відновлення
31 січня 2017 року GitLab.com утратив частину даних основної бази. Під час спроби повторно синхронізувати відстаючу репліку інженер мав очистити каталог вторинного вузла, але небезпечну команду виконав на основному. Самої помилки було недостатньо для довгої аварії: резервні копії pg_dump не з’явилися в сховищі, оскільки завдання використовувало pg_dump 9.2 для PostgreSQL 9.6 і завершувалося з помилкою; листи про збій відхилялися через проблему з Domain-based Message Authentication, Reporting, and Conformance (DMARC). Журнал змін WAL не архівували, а репліку теж було очищено під час повторного створення. (GitLab: постмортем аварії бази 31 січня, 10.02.2017.)
Доступним варіантом стала ручна копія через Logical Volume Manager (LVM — менеджер логічних томів), зроблена приблизно за шість годин до аварії для тестового середовища. Для відновлення GitLab скопіював базу зі staging на виробничий вузол; повільні мережеві диски спричинили близько 18 годин копіювання. Webhooks відновлювали окремо з іншого екземпляра тієї копії, а послідовності ідентифікаторів збільшили, щоб не повторно використати номери, які могли вже існувати після втраченої ділянки. Постмортем оцінює втрату записів між 17:20 і приблизно 23:30 за координованим всесвітнім часом (Coordinated Universal Time, UTC) того дня; інша частина звіту округлює кінець вікна до 00:00, тому час наведено приблизно. Git-репозиторії та вікі зберігалися окремо й не постраждали. (GitLab: деталі відновлення та оцінка втрати даних.)
Це не приклад невдалого відкоту випуску: це приклад відновлення бази, де кожен припущений запасний шлях мав власний пробіл — помилкову ціль руйнівної дії, реплікацію без архіву журналів, копію, що не створювалася, недоставлені сповіщення та відновлення з повільної копії в іншому середовищі. Висновок — не звинувачувати одного оператора й не вважати одну міру універсальною. Сам GitLab зафіксував проблеми видимості вузлів, моніторингу копій, перевірки відновлення й відповідальності за збереження даних. Технічні деталі описують його систему 2017 року й не є рекомендацією щодо нинішньої конфігурації GitLab.
60.12. Межі дій програмного агента
Агент може допомогти зібрати ідентифікатори версій, знайти копію, обчислити різницю між станами, перевірити метрики чи підготувати план звірки. Це не означає, що він має сам обрати момент відновлення або перезаписати робочу базу. Перед зміною агент має показати точну ціль, область дії, очікувану втрату після точки, виявлені невизначеності й спосіб перевірки результату.
Для потенційно руйнівної дії агент повинен:
- підтвердити ідентичність середовища, екземпляра, регіону, сховища й обраної копії безпосередньо перед запуском;
- працювати з найменшими потрібними правами та відокремленою копією; спочатку готувати план і звіт порівняння;
- не видаляти первинні файли, не стирати журнал і не відновлювати поверх чинного джерела, якщо це не є чітко дозволеною та перевіреною дією;
- отримати явне схвалення уповноваженої людини перед незворотним виробничим перемиканням або прийняттям втрати записів;
- зупинитися, якщо точку не можна визначити, перевірка доступу чи журналювання недоступна, або зовнішня операція має невідомий результат; не повторювати дію навмання.
Документація OpenAI для Agents SDK (Software Development Kit — набір для розробки програмного забезпечення) описує схему, де чутливий виклик інструмента призупиняється для людського схвалення, а повторне продовження використовує той самий стан запуску. Документація Claude Code окремо показує, що режими дозволів задають базову межу між автономністю та наглядом, а доступність команди не означає її безпечність. Це приклади реалізації меж агента, а не заміна політики власника даних. (OpenAI Agents SDK: захисні правила й людська перевірка, переглянуто 24.09.2026; Claude Code: режими дозволів, переглянуто 24.09.2026.)
Короткий підсумок
Відкат коду, перемикання на репліку, виправлення даних, відновлення копії та компенсація зовнішнього ефекту змінюють різні частини системи. Спочатку визначте, що саме пошкоджено й до якої доведеної точки треба повернути стан. Перевірте сумісність версій, журналів, конфігурації та залежностей; створіть ізольовану копію; звірте інваріанти й зміни після точки; лише тоді приймайте рішення про джерело запису. RPO та RTO належать продукту й бізнесу. Файл копії або зелений статус завдання не доводять, що застосунок можна відновити.
Джерела та подальше читання
Матеріали перевірено 24 вересня 2026 року. Технічна поведінка в прикладах прив’язана до названих нижче версій і постачальників; перед реальним відновленням її потрібно звірити з фактичною системою.
- PostgreSQL 18, Continuous Archiving and Point-in-Time Recovery — базові копії, WAL, ціль відновлення, вимоги до повноти архіву, послідовність та перевірка відновленої бази.
- PostgreSQL 18, Write-Ahead Log configuration — рівні журналювання та цілі відновлення; поведінка й параметри залежать від версії.
- Amazon RDS, відновлення екземпляра бази даних до заданої точки в часі — приклад відновлення до нового керованого екземпляра, період зберігання й рушій-специфічні застереження.
- Google Cloud Architecture Center, Architecting disaster recovery for cloud infrastructure outages, переглянуто 10 травня 2024 року — бізнесовий зміст RPO і RTO та різні цілі для застосунків різної критичності.
- Google Cloud Well-Architected Framework, Perform testing for recovery from data loss, переглянуто 30 грудня 2024 року — перевірка цілісності, RPO/RTO та стека застосунку на відновлених даних у непродукційному середовищі.
- Google, Site Reliability Engineering: Data Integrity, 2016 — розрізнення реплікації й відновлюваності та орієнтація плану копій на фактичне повернення даних.
- GitLab, Postmortem of database outage of January 31, опубліковано 10 лютого 2017 року — первинний опис помилкового вузла, несправного резервного завдання, відсутнього архіву WAL, реального відновлення й втраченої ділянки даних.
- OpenAI, Agents SDK: Guardrails and human review, перевірено 24 вересня 2026 року — переривання чутливого виклику інструмента для схвалення людиною, його продовження та перевірка безпосередньо біля ефекту.
- Anthropic, Claude Code permission modes, перевірено 24 вересня 2026 року — межі дозволів, підтвердження та розподіл повноважень між агентом і середовищем.
- Martin Kleppmann, Chris Riccomini, Designing Data-Intensive Applications (DDIA — проєктування застосунків із насиченою роботою з даними), 2nd edition, O’Reilly, лютий 2026 року — концептуальний контекст реплікації, узгодженості й надійності даних; конкретні процедури цього розділу взято з актуальної документації PostgreSQL і постачальників.
- Neal Ford, Mark Richards, Pramod Sadalage, Zhamak Dehghani, Software Architecture: The Hard Parts, Chapter 6: Pulling Apart Operational Data, O’Reilly, жовтень 2021 року — контекст про власність операційних даних і наслідки поділу сховищ для звірки та відновлення.