DevOps не пишет запросы за разработчиков, но отвечает за то, чтобы база не потеряла данные, пережила отказ сервера и обновлялась без простоя. Примеры на PostgreSQL: его чаще всего спрашивают в РФ.
RPO и RTO
- RPO (Recovery Point Objective): сколько данных можно потерять. «Не больше 5 минут» значит, что бэкап раз в сутки не подходит.
- RTO (Recovery Time Objective): за сколько надо восстановиться. «Час» значит, что восстановление 2 ТБ из логического дампа за 10 часов не подходит.
Сначала договариваются о RPO и RTO с бизнесом, потом выбирают способ бэкапа.
Логические и физические бэкапы
- Логический (
pg_dump): SQL или собственный формат с данными одной базы. Согласован на момент начала дампа, переносим между версиями, можно восстановить одну таблицу. Минусы: долго на больших базах, восстановление ещё дольше (пересоздание индексов), точка восстановления только момент дампа. - Физический (
pg_basebackup, pgBackRest, WAL-G, Barman): копия файлов кластера плюс журнал WAL. Быстрое восстановление больших баз и PITR (point-in-time recovery): восстановиться на любой момент, например на 14:31:59, за секунду до того, как кто-то выполнилDELETEбезWHERE.
pg_dump -Fc -d app -f app.dump # формат custom, сжатый
pg_restore -d app_restored -j 4 app.dump # восстановление в 4 потока
PITR работает так: базовая копия плюс непрерывно архивируемые сегменты WAL. При восстановлении берут базовую копию и проигрывают WAL до нужного момента (recovery_target_time).
Правила бэкапов
- 3-2-1: три копии, на двух разных типах носителей, одна вне площадки. Бэкап на том же диске или в том же аккаунте облака не спасёт от удаления аккаунта или шифровальщика.
- Неизменяемость: объектное хранилище с блокировкой объектов или отдельный аккаунт без права удаления.
- Проверка восстановления: бэкап, из которого ни разу не восстанавливались, это гипотеза. Регулярно восстанавливайте на отдельный стенд автоматически и проверяйте данные.
- Мониторинг: алерт, если бэкап не создался или стал подозрительно маленьким.
Репликация
- Потоковая (физическая): реплика получает WAL с мастера и применяет его. Реплики можно использовать для чтения и как кандидатов на failover.
- Асинхронная (по умолчанию): мастер не ждёт реплику, при падении мастера последние транзакции могут потеряться.
- Синхронная: коммит ждёт подтверждения реплики (
synchronous_standby_names). Надёжнее, но медленнее, и если синхронная реплика недоступна, запись встанет, если не настроить запасную. - Логическая (publication / subscription): передаёт изменения строк, работает между разными мажорными версиями. Используют для обновлений почти без простоя и для выборочной репликации.
Лаг репликации нужно мониторить: чтение с отстающей реплики возвращает старые данные («создал заказ, а в списке его нет»).
Failover
Автоматическое переключение на реплику делают Patroni (с etcd или Consul для выбора лидера), в managed-базах облако. Главная опасность split-brain: два узла считают себя мастером и принимают запись. Защищаются консенсусом (лидер только с большинством голосов) и fencing: старый мастер отключают от записи. Приложение должно переподключаться: через виртуальный IP, DNS, HAProxy или PgBouncer, который знает текущего лидера.
Пулы соединений
Каждое соединение PostgreSQL это отдельный процесс с памятью. Тысяча подов по 20 соединений исчерпают max_connections и память. PgBouncer держит небольшое число серверных соединений и раздаёт их клиентам:
session: соединение закреплено за клиентом на всю сессию;transaction: только на время транзакции, самый эффективный режим. Не работают сессионные вещи:SETбезLOCAL, advisory-блокировки уровня сессии,LISTEN;statement: на один запрос, транзакции из нескольких запросов невозможны.
Миграции без простоя
Проблема не в длительности миграции, а в блокировках. Многие ALTER TABLE берут блокировку ACCESS EXCLUSIVE, и пока она ждёт долгий запрос, за ней в очереди встают все остальные запросы к таблице. Правила:
SET lock_timeout = '3s'в миграции: лучше упасть и повторить, чем повесить всю таблицу.CREATE INDEX CONCURRENTLYвместо обычного (не внутри транзакции; при ошибке остаётся невалидный индекс, его удаляют и создают снова).- Добавление колонки с константным DEFAULT быстрое с PostgreSQL 11, а смена типа колонки часто переписывает всю таблицу.
- Внешний ключ и CHECK: сначала
ADD CONSTRAINT ... NOT VALID(быстро), потомVALIDATE CONSTRAINT(проверка без блокировки записи). - Массовые
UPDATEпачками по несколько тысяч строк, а не одним запросом на 50 миллионов. - Переименование и удаление колонок только через expand/contract.
Мажорное обновление
Варианты: pg_upgrade (быстро с --link, но с простоем на время работы), логическая репликация в новый кластер с переключением (минуты простоя), дамп и восстановление (долго, для небольших баз). Всегда с репетицией на копии.
Частые ошибки
- Бэкапы есть, восстановление ни разу не проверяли.
- Бэкапы в том же облачном аккаунте, что и база.
- Каждый под открывает 50 соединений напрямую к базе.
CREATE INDEXбезCONCURRENTLYна горячей таблице в рабочее время.- Чтение с асинхронной реплики сразу после записи.
Что спросят на собесе
- Чем логический бэкап отличается от физического и что такое PITR.
- Что такое RPO и RTO и как от них зависит стратегия.
- Синхронная и асинхронная репликация, что такое split-brain.
- Зачем PgBouncer и какие у него режимы.
- Как добавить индекс или внешний ключ на большую таблицу без простоя.