# PostgreSQL с 10-й версии на 17-ю за одно окно

## Что было

SaaS-платформа документооборота: два публичных фронта, около двадцати пяти микросервисов, кластер Kubernetes старше четырёх лет. Под всем этим — PostgreSQL десятой версии, снятой с поддержки несколько лет назад.

Ситуация обычная для системы, которая выросла из стартапа: база работает, трогать страшно, а список причин перестать откладывать копится:

- версия давно без обновлений безопасности;
- новые возможности планировщика и мониторинга недоступны;
- инструменты вокруг базы постепенно перестают поддерживать старую ветку;
- разница между десятой и семнадцатой версиями — семь мажорных выпусков, то есть накопленные несовместимости в правах, ролях и умолчаниях.

Требование бизнеса: простой не дольше трёх часов, ночью, с гарантией возврата назад, если что-то пойдёт не так.

## Как делали

**Метод — логическая репликация.** Новый сервер поднимается рядом на семнадцатой версии, данные едут на него заранее и держатся в актуальном состоянии. В окно остаётся только догнать последние изменения и переключить приложения на новый адрес. Обновление на месте отпадало сразу: оно требует остановки на всё время конвертации и не оставляет пути назад.

**Сверка структуры до окна.** Пересчитали и сравнили таблицы, колонки, ограничения, счётчики идентификаторов, права и роли. Разница между версиями вылезает именно здесь: то, что в десятой было умолчанием, в семнадцатой требует явной выдачи прав.

**Репетиция на тестовом контуре.** Прогнали окно целиком, по командам, как в бою. Репетиция вскрыла три ошибки в готовых командах, каждая из которых сорвала бы работы: не срабатывал разрыв пользовательских соединений, команда остановки сервисов не работала в оболочке инженера, а критерий готовности приложений давал ложное «готово». Все три исправлены и перепроверены до боевого окна.

**Заранее написанные команды.** К окну готовится файл, где каждый шаг — готовая строка с проверкой результата. В три часа ночи никто ничего не сочиняет и не вспоминает синтаксис.

**Точка принятия решения.** Перед самим переключением — формальная проверка «идём или не идём»: лаг подписки, состояние копий, готовность отката. Не сошлось — расходимся и переносим, потери минимальные.

![Логическая репликация PostgreSQL 10 в 17, проверка готовности и фактическое окно 1 час 47 минут](/images/illustrations/part2/15-case-postgresql.webp)

## Результат

| Что | Итог |
|---|---|
| Окно работ | **1 час 47 минут** при заявленных бизнесу трёх часах |
| Данные | перенесены полностью, подписчик дошёл до финальной LSN |
| Структура | 199 таблиц, 1 593 колонки, 189 счётчиков, 409 ограничений — сошлось до единицы |
| Счётчики идентификаторов | 168 расхождений найдено и исправлено до открытия |
| Сервисы | все 16 подняты в штатном числе копий |
| Проверка действием | чтение и запись боевых данных прошли до открытия входа |
| Ошибки в журнале после открытия | ноль за четыре часа наблюдения |
| Откат | не потребовался |

Три сбоя в окне всё-таки случились: подвисшие приложения на одном узле, отказ того же узла запускать новые копии и заглушка технических работ, мешавшая внутренним вызовам при приёмке. Все три разобраны на месте и уложились в окно — именно на такие случаи в плане и закладывается запас.

## Что было после

Работы не заканчиваются переключением. Дальше — пересборка резервной реплики уже на новой версии, первая полная копия новой базы, настройка сбора метрик под новый сервер и наблюдение за первыми сутками.

## Что забрал заказчик

Базу, которая снова получает обновления безопасности, и описанную процедуру: как готовились, как переключали, что проверяли и по каким признакам решали, что можно открывать пользователей. Следующее такое обновление будет уже не приключением, а рутиной по инструкции.