Всю профессиональную карьеру я так или иначе жил рядом с базами данных: начинал с 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: меньше фич, меньше расширяемость, более строгие ограничения на запросы/транзакции?
