Всю профессиональную карьеру я так или иначе жил рядом с базами данных: начинал с Oracle, потом надолго перешёл на MS SQL Server и PostgreSQL (думаю, я здесь не один такой).
Обычно мы используем СУБД как инструмент: учитываем нюансы синтаксиса, оптимизатора, утилит и поведения движка — и решаем прикладные задачи. Но недавно, разворачивая очередной PostgreSQL‑кластер для продакшена, я поймал себя на мысли: не слишком ли много всего нужно поднять вокруг PostgreSQL, чтобы система работала одновременно безопасно и предсказуемо по производительности?
Это не пост “против PostgreSQL”. Скорее попытка разобраться, почему эксплуатация OLTP‑БД всё чаще превращается в конструктор — и что бы я ожидал от базы данных, если проектировать её сегодня, под реалии 2026 года.
Что изменилось за последние годы
Законы физики не поменялись: I/O всё ещё медленнее CPU и памяти. Но контекст вокруг баз данных изменился радикально:
-
Объёмы данных и число пользователей в продакшене выросли.
-
Железо стало другим: NVMe, большие объёмы RAM, другие профили задержек и параллелизма.
-
Среда эксплуатации стала другой: виртуализация, контейнеры, Kubernetes, immutable‑подходы, GitOps.
-
Поменялись модели использования: multi‑tenant SaaS (“одна БД на тысячи арендаторов”) или, наоборот — множество небольших инстансов.
-
Выросла планка безопасности и комплаенса: аудит, контроль ключей, минимизация доверенной базы (TCB), и threat model “ошибки и компрометации случаются”.
-
Появились языки и практики, которые повышают ожидания к качеству системного кода: Rust с идеей memory safety и Go как практичный язык для инфраструктурных систем. (Например, команда CockroachDB отдельно описывала, почему для их распределённой БД Go оказался удачным выбором: Why Go was the right choice for CockroachDB.)
Почему появляется “слой магии”
В таких условиях многие важные свойства продакшен‑системы получаются не из фундаментального контракта ядра, а из комбинации:
-
правильных настроек,
-
правильного операционного режима,
-
правильного набора расширений и инструментов,
-
правильного деплоя и практик команды.
И всё бы ничего, но эксплуатация превращается в область, где сложно отличить “архитектурное ограничение” от “мы недонастроили одну из двадцати вещей”.
Какие есть классы SQL‑БД (и почему я смотрю на OLTP)
Я попробовал оглядеться: может, проблема решена “рынком” и давно есть зрелые альтернативы, которые просто нужно начать использовать.
Если не брать в расчёт NoSQL (я сознательно говорю именно про транзакционный SQL‑слой), то в целом современные системы можно разделить на несколько классов:
-
Распределённые SQL (NewSQL): CockroachDB, YugabyteDB, TiDB.
-
Аналитические SQL (OLAP/MPP): ClickHouse, SingleStore.
-
Embedded / локальные SQL: SQLite, DuckDB.
-
Классические OLTP: и вот здесь, как ни странно, “полностью новых” игроков заметно меньше, чем ожидаешь.
И это возвращает меня к мысли: если менять фундамент зрелой OLTP‑СУБД сложно и рискованно, то интересно не только “что есть”, но и “какие свойства вообще должны быть у OLTP‑БД, если проектировать с нуля под текущую реальность”.
Типовые боли OLTP: PostgreSQL и MS SQL Server
Чтобы не опираться только на личный опыт, я собрал типовые проблемы, которые чаще всего всплывают в эксплуатации PostgreSQL и MS SQL Server (не как сравнение “кто хуже”, а как список классов сложностей, да тут еще можно было бы включить MySql и Oracle, но я себя пожалел ).
PostgreSQL (OLTP)
-
Autovacuum не успевает → bloat таблиц/индексов: из‑за MVCC “мёртвые” версии строк копятся, растёт размер таблиц, ухудшаются задержки (см. официально про вакуум и его роль в поддержании производительности и освобождении пространства: PostgreSQL docs — Routine Vacuuming).
-
Длинные транзакции / idle in transaction блокируют уборку: пока открытая транзакция держит старый snapshot, vacuum не может удалить версии строк, которые потенциально ещё видимы этой транзакции (хороший разбор практических симптомов и причин: Citus — Debugging Postgres autovacuum problems).
-
Wraparound pressure и freeze‑работы: вакуум (включая freeze) — обязательная часть жизненного цикла; при достижении порогов по “возрасту” транзакций может потребоваться тяжёлая фоновая работа (PostgreSQL docs — Routine Vacuuming).
-
Масштабирование по соединениям: PostgreSQL использует модель “process per connection” (каждое подключение обслуживается отдельным backend‑процессом), поэтому при большом числе клиентов почти неизбежно возникает потребность в пулере и дисциплине по соединениям (официально про установление соединений и роль postmaster: PostgreSQL docs — How Connections Are Established).
-
Память “умножается” под нагрузкой: при большом числе параллельных запросов легко получить неожиданный рост RSS, если не учитывать модель выделения памяти на операции (сортировки/хэши и т.п.).
MS SQL Server (OLTP)
-
Blocking и lock escalation: при накоплении большого числа locks возможна эскалация, что усиливает блокировки для конкурирующих транзакций (Microsoft описывает причины и подходы к диагностике/снижению: Resolve blocking problem caused by lock escalation).
-
Parameter sniffing → “то быстро, то медленно”: план кэшируется под один набор параметров, а на другом резко деградирует (частая причина нестабильной OLTP‑латентности).
-
Tempdb contention: активное использование temp tables/сортировок/версионирования может превратить tempdb в узкое место (особенно при неидеальной конфигурации).
-
Цена “покрывающих” индексов и широких INCLUDE: ускоряют чтения, но повышают стоимость DML и общий размер индексов.
-
План‑кэш и single-use ad‑hoc планы: при потоке уникальных запросов может раздуваться план‑кэш; у Microsoft есть отдельная рекомендация и настройка
optimize for ad hoc workloadsкак раз для сценария с большим числом single‑use ad‑hoc batches: optimize for ad hoc workloads (server configuration option).
Общее для обеих (проявляется по‑разному)
-
Слишком много индексов: чтения быстрее, но записи резко дорожают; со временем индексный “долг” становится главным ограничением throughput.
-
Плохой дизайн транзакций: большие транзакции, удержание ресурсов дольше нужного, “чатти” доступ — усиливают и блокировки, и проблемы горизонта видимости MVCC.
-
Неподходящий паттерн соединений: тысячи коротких коннектов вместо пула почти всегда приводят к деградации (в PostgreSQL обычно острее из‑за process-per-connection модели) — см. модель соединений в доках PostgreSQL: How Connections Are Established.
Мой вывод: не “новая фича”, а новый контракт
Я для себя сформулировал мысль так:
Если OLTP‑БД в 2026 должна быть продакшен‑готовой, то ключевые свойства должны быть контрактом ядра, а не результатом тонкой настройки окружающей экосистемы.
Под “контрактом” я имею в виду гарантии вида:
-
“если включено X, это нельзя обойти молча”,
-
“фоновые процессы не могут бесконтрольно съесть latency‑бюджет”,
-
“если контекст безопасности не задан — запрос не выполняется”,
-
“аудит нельзя выключить так, чтобы никто не заметил”.
В следующей статье я продолжу эту линию: попробую собрать список требований к “OLTP‑БД с нуля в 2026”, а затем выбрать 1–2 пункта и разобрать их глубже (через реальные негативные сценарии и компромиссы, которые обычно скрыты за словом “просто включите настройку”).
Вопросы к сообществу (DBA / Ops)
Какие 3 вещи вы считаете “обязательными для продакшена” в OLTP‑БД в 2026 (без чего вы не подпишете запуск)?
-
Что у вас болит сильнее: tail latency (p99/p99.9), обслуживание (vacuum/maintenance), или безопасность/комплаенс (аудит/ключи/изоляция)?
-
Какие инциденты у вас повторяются чаще всего: bloat/vacuum, blocking/lock storms, спайки COMMIT, деградация планов, проблемы с соединениями?
-
Какой минимальный набор обвязки вокруг PostgreSQL вы считаете обязательным (pooler, бэкапы, мониторинг, алерты, аудит, шифрование, политики доступа)?
-
Где для вас проходит граница “это должна уметь БД” vs “это должна решать платформа вокруг” (оператор в K8s, service mesh, внешний KMS, внешние политики)?
-
Нужен ли вам fail‑closed режим по умолчанию (нельзя забыть включить критичные меры), или важнее гибкость/совместимость?
Вопросы к сообществу (разработчики / архитекторы)
-
В какой модели вы чаще живёте: один продукт — одна БД, или multi‑tenant SaaS (много арендаторов в одной БД/схеме/таблицах)?
-
Что для вас важнее как для потребителя БД: “простая эксплуатация платформой” или “максимум возможностей в самой БД (фичи/расширяемость)”?
-
PL/pgSQL / T‑SQL и вообще процедурный язык в БД: насколько он вам реально нужен сегодня? (Бизнес‑логика рядом с данными, триггеры, миграции, ETL, “тонкие” функции; или лучше всё держать в приложении и ограничиться SQL?)
-
Если бы процедурный язык был опциональным модулем, какие требования вы бы к нему предъявили (безопасность, песочница, производительность, наблюдаемость)?
-
Какие компромиссы вы готовы принять ради предсказуемого p99: меньше фич, меньше расширяемость, более строгие ограничения на запросы/транзакции?
Автор: anishukserg
