Контракт вместо настроек: чего я жду от OLTP-БД в 2026

После первой статьи в комментариях несколько раз прозвучало примерно одно и то же:
"Всё правильно, но это же про любую зрелую СУБД — что с этим делать?"

Я думал над этим вопросом несколько недель. И в итоге решил не искать ответ в виде
"возьмите правильный инструмент X" — а попробовать честно сформулировать:
какими свойствами OLTP-БД должна обладать сама по себе, независимо от того,
насколько хорош ваш оператор, консультант или runbook.

Здесь две части:

  • Что я называю "контрактом" БД — и почему это важнее списка фич.

  • Сценарии из реальной эксплуатации — и какие механизмы их предотвращают.

А в конце — самое интересное, к чему это все меня привело...

Что такое "контракт" — и почему это не маркетинг

Попробую объяснить не через определение, а через ощущение.

Когда вы покупаете автомобиль, вы не читаете инструкцию к тормозам каждое утро.
Вы просто знаете: нажал педаль — машина тормозит. Это контракт. Он не зависит от того,
правильно ли вы настроили тормозную жидкость этим утром или не забыли включить
"режим торможения" в меню.

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

  • правильно настроено,

  • правильно задеплоено,

  • и команда не забыла включить нужную опцию.

Это не контракт. Это договорённость, которая легко рассыпается при смене команды,
росте нагрузки или очередном обновлении.

Контракт БД — это проверяемые гарантии, которые либо выполняются всегда,
либо система явно сообщает об отказе. Без тихих исключений, без
"ну мы же предупреждали в документации".

Чтобы контракт был настоящим, а не декларативным, он должен быть:

  • формализован — можно проверить программно, не только "на глаз";

  • наблюдаем — есть метрики/события на каждое нарушение;

  • fail-closed по умолчанию — если условие не выполнено, система отказывает предсказуемо;

  • одинаково понятен разработчику, DBA и SRE — не только автору конфига.


10 свойств, с которых должен начинаться продакшен

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

Безопасность: нельзя "забыть включить"

1. Нет контекста — нет запроса. Если для выполнения DML/DDL нужен security context
(например, tenant_id), а он не задан — запрос просто не исполняется.
Это звучит жёстко, но альтернатива хуже: "невинный" admin-скрипт без контекста
превращается в источник утечки между клиентами. Да, это поднимает планку
для ad-hoc запросов и миграций — но это сознательный компромисс.

2. Аудит нельзя выключить незаметно. Аудит — не флаг, который включают по настроению.
Это часть контракта исполнения: попытка обойти или отключить фиксируется и алертит.
Без этого после инцидента вы гарантированно услышите "мы не можем восстановить картину".
Нужна политика ретенции и фильтрации, иначе аудит превратится в гору логов —
но это проблема операционная, а не архитектурная.

Предсказуемость под нагрузкой: "не должно быть сюрпризов"

3. Фоновые процессы не едят latency-бюджет бесконтрольно. Каждый, кто эксплуатировал
PostgreSQL на большом объёме, знает ощущение: "вакуум опять всё сожрал".
Maintenance (cleanup, compaction, freeze-подобные задачи) должен быть ограничен
по влиянию на интерактивный трафик. Фоновая уборка может быть медленнее — зато p99
не "срывается" в самый неподходящий момент.

4. Память предсказуема по классам нагрузки. 50 параллельных сортировок не должны
молча удвоить RSS и убить соседей. Тяжёлые запросы могут получить throttle
или явный отказ — но это лучше, чем OOM посреди пика.

5. Наплыв соединений — политика, а не "как получится". Queue, reject, backpressure —
что угодно, но явно описанное. Не "иногда повезло подключиться, иногда нет".
Часть клиентов получит предсказуемый отказ вместо зависания на 30 секунд — и это нормально.

6. Длинные транзакции и горячие конфликты под контролем ядра. Лимиты на длительность
и размер транзакции по классам workload. Раннее обнаружение lock-конфликтов.
Контролируемый abort с диагностикой, а не "всё зависло и непонятно почему".
Некоторые "длинные бизнес-операции" придётся разбивать — но это рефакторинг,
а не катастрофа.

7. Деградация планов — не сюрприз. Каждый DBA хотя бы раз видел:
"вчера быстро, сегодня медленно — ничего не менялось". На деле менялась статистика
или параметры, и план тихо "уехал". Должны быть управляемые рамки:
что может поменяться автоматически, а что — только по явному действию.
Часть агрессивных оптимизаций может быть отключена ради стабильности — и это ок.

Multi-tenant: "чужой шум — не моя проблема"

8. Изоляция арендаторов — примитив ядра. Если один "шумный" арендатор
может просадить latency у всех остальных, у вас нет SLA — у вас есть надежда.
Изоляция ресурсов (CPU/memory/IO/locks) должна быть встроена,
а не достраиваться оркестратором. Лимиты жёстче, квоты нужно явно выдавать —
но зато "noisy neighbor" перестаёт быть системным риском.

9. Режимы деградации описаны заранее. Что происходит на пике?
Что отбрасывается первым? Что приоритизируется? Если у системы нет ответа —
каждый постмортем будет начинаться с нуля. Бизнес должен принять,
что некоторые операции в критичной ситуации будут отвергнуты — но лучше заранее
договориться "что жертвуем", чем каждый раз "гадать, что упало".

Наблюдаемость: "мы думали, что включено"

10. Каждая гарантия наблюдаема. Это замыкающее свойство. Если у гарантий 1–9
нет метрик/событий, которые можно проверить до инцидента, — они существуют только
на бумаге. "Мы думали, что включено" — это не баг эксплуатации,
это архитектурный долг. Да, телеметрия стоит ресурсов и требует дисциплины
по SLO/алертам — но без неё вы летите вслепую.


7 историй о том, как p99 "срывается"

Теперь — практика. Ниже не абстрактные "failure modes", а узнаваемые ситуации,
которые повторяются в разных стеках. Если вы узнали хотя бы две — значит,
список гарантий выше не теоретический.


"Транзакция, которая не отпускает"

Пятница, вечер. Мониторинг показывает: p99 растёт волнами, таблицы медленно
раздуваются, фоновая уборка отстаёт. Никто ничего не деплоил. Через час
находите: забытая транзакция в idle-in-transaction, открыта 4 часа назад из
скрипта миграции, который давно закончился. Она держит snapshot, а значит —
ни vacuum, ни cleanup не могут убрать старые версии.

Что должно быть в ядре: жёсткие лимиты на длительность транзакции по классам
workload. Если транзакция приближается к лимиту — контролируемый abort
с понятной диагностикой. Остальной трафик продолжает работать.


"Релиз, который всё сломал (но CPU в норме)"

Понедельник после релиза. Часть API уходит в таймауты. Первое, что смотрят — CPU.
Нормально. Второе — диск. Нормально. Третье — "а что поменялось?"
Оказывается, новый код добавил UPDATE по горячей таблице в другом порядке,
и зона конфликта блокировок расширилась. Очередь ожиданий растёт,
а прямого "bottleneck" нет — есть только цепочка ожиданий.

Что должно быть в ядре: lock budget per query/txn. Раннее обнаружение
конфликтных графов. Политика: "если конфликт затянулся — abort наименее
приоритетной операции, критичный путь остаётся живым."


"Вакуум (или что-то похожее) опять всё съел"

Каждый день в 14:00 p99 на 5 минут уходит в небо. Потом "само" возвращается.
DBA говорит: "это вакуум". Ops говорит: "надо просто пережить".
Бизнес говорит: "а почему мы это обнаруживаем каждый раз случайно?"

Что должно быть в ядре: scheduler для фоновых задач, привязанный
к SLO интерактивного трафика. Если онлайн-нагрузка растёт — фоновая работа
автоматически дросселируется. Даже если это удлиняет обслуживание — предсказуемость
важнее скорости уборки.


"Все подключились одновременно"

Деплой микросервисов. 200 подов стартуют, каждый открывает по 10 коннектов.
2000 соединений за 30 секунд. БД не успевает — начинается каскад таймаутов.
Приложение ретраит — становится хуже. Через 5 минут всё лежит, хотя сама БД
"технически жива".

Что должно быть в ядре: admission control на входе. Очередь с TTL.
Явная политика: "новые низкоприоритетные подключения — reject,
существующие критичные потоки не деградируют".


"Один клиент положил всех"

Multi-tenant SaaS. У "тихих" арендаторов растёт latency.
Ничего не менялось — кроме того, что один крупный клиент запустил
массовый импорт. Его нагрузка забрала IO-бюджет, и "соседи" просели.

Что должно быть в ядре: tenant-aware планировщик. Лимиты на CPU/memory/IO
по арендаторам. Наблюдаемость: "кто у кого отнял бюджет".
"Шумный" арендатор получает throttle — а не деградацию всей популяции.


"Временное исключение стало постоянным"

После инцидента безопасности: "кто это сделал?" — "не можем установить,
аудит был отключён для этой схемы... временно... три месяца назад."

Что должно быть в ядре: security context и аудит — неотключаемая часть
исполнения. Операция без требуемого контекста не выполняется. Точка.
Не "можно обойти, если знаешь как".


"Вчера быстро, сегодня медленно — ничего не менялось"

Тот же endpoint, похожие данные, но время ответа выросло в 5 раз.
"А что изменилось?" — "Ничего." На самом деле поменялась статистика
(или параметры), и оптимизатор выбрал другой план. Воспроизвести сложно,
откатить — непонятно куда.

Что должно быть в ядре: контролируемые режимы стабильности планов.
Обнаружение опасных регрессий до массового эффекта. Откат к стабильной стратегии,
даже если она не самая быстрая "в среднем" — потому что "в среднем" никого
не волнует, когда горит p99.


Граница между БД и платформой

Kubernetes-операторы, service mesh, внешние политики — всё это важно.
Но есть вещи, которые опасно оставлять снаружи:

  • контроль security context на уровне запроса;

  • инварианты аудита;

  • защита latency-бюджета от внутренних фоновых процессов;

  • изоляция арендаторов в shared deployment.

Если эти свойства не являются контрактом БД, платформа в лучшем случае
маскирует проблему, а не решает её.

Простой способ проверить себя: пройдитесь по списку из 10 свойств выше
и честно ответьте на один вопрос по каждому пункту — это свойство ядра
или это runbook. Не нужно считать баллы. Обычно достаточно двух-трёх ответов
"это runbook", чтобы понять, где именно у вас хрупкость.


Как я пришёл к мысли о проектировании БД с нуля

Оговорюсь: эти мысли я формулировал не параллельно с написанием статьи.
Всё описанное ниже — это ретроспектива примерно полугодового пути,
который привёл к конкретному решению. Статья — просто попытка выстроить
это в логику, понятную без контекста.

Параллельно с размышлениями о БД в свободное время от работы я несколько месяцев изучал Rust — не потому что "модно",
а потому что язык меня зацепил именно философией: он делает невозможными целые классы ошибок,
которые в других языках просто "иногда случаются".
Никаких скрытых аллокаций в неподходящий момент.
Никакого GC, который сам решает, когда ему удобно почистить память.
Явные инварианты прямо в системе типов, гарантии которые дает язык.
Отправной точкой для погружения в Rust стала статья https://habr.com/ru/companies/bitrix/articles/878912/.
И в какой-то момент два потока мыслей про проблемы СУБД и Rust сошлись: Rust на этапе компиляции запрещает написать код, который может упасть в рантайме из-за памяти. Он навязывает контракт разработчику. Я понял, что хочу того же от базы данных: чтобы она навязывала контракт приложению, запрещая запросы, которые могут положить БД.

Я описывал требования к "правильной БД" — предсказуемое поведение под нагрузкой,
контракты вместо настроек, никаких фоновых сюрпризов — и это звучало
как описание того, для чего Rust и создавался.
Язык, который не позволяет "случайно забыть" важное.
Именно это я хотел от базы данных.

Я стал смотреть: а есть ли что-то живое на Rust в мире OLTP?
Нашёл несколько экспериментов, пару заброшенных репозиториев,
один академический проект. Ничего, что выглядело бы как
"это решает проблему, которую я описал выше".

Следующий очевидный вопрос: "А почему не CockroachDB или YugabyteDB?"
Потому что они решают другую задачу — распределённость.
Мне нужна предсказуемая одноузловая OLTP с правильными примитивами в ядре.
"А почему не форк Postgres?" — потому что это значит бороться с
тридцатью годами обратной совместимости и C-кодовой базы.
Это не критика — это просто другой вектор.

Вот тогда и появилась мысль: а что если попробовать самому?
Не "написать базу данных" как самоцель —
а начать с честного списка архитектурных решений:
что должно быть в ядре обязательно, что сознательно остаётся за рамками v1,
и почему. К чему это все привело — расскажу уже в следующей статье.

В следующей статье я разберу именно это: как контрактные гарантии из этого списка
превращаются в конкретные архитектурные примитивы — и что это значит
на практике, когда начинаешь с чистого листа.

P.S. Под p99 я в этой статье имею в виду 99-й персентиль latency, но важна оговорка: сам по себе p99 ничего не значит без ответа на вопрос “чего именно?”. Для OLTP меня интересует не средняя температура по больнице, а хвост деградации: время запроса, commit latency, ожидание блокировок, всплески на fsync/checkpoint. Иными словами, речь о предсказуемости под нагрузкой, а не об одной красивой цифре.

Комментарии (10)


  1. pg_expecto
    10.03.2026 05:15

    нажал педаль — машина тормозит. Это контракт. Он не зависит от того,правильно ли вы настроили тормозную жидкость этим утром

    Извините , но аллегория выбрана неудачно. Тормоза нуждаются в настройке и мониторинге . и только при 100% исправности тормозной системы контракт будет выполнен. К тому, же при одном важном условии - на сухой поверхности и на льду контракт будет выполнен по разному , с разными итоговыми результатами. Как тормозит это очень важно.

    Если перенести аллегорию на СУБД - контракт это операционная доступность - СУБД работает и выдаёт данные. Но, не менее важные и производительность - как СУБД выдаёт данные. Хотя конечно производительность в рамки контракта очень сложно поместить(по крайней мере, я пока не встречал примеров). Ну просто потому, что как правило никто и не задумывается - а производительность это что и как её считать. Работает и ладно.А будет , как кажется тормозить- накидают ядер и памяти и диски HiOPS.

    P.S.

    • формализован — можно проверить программно, не только "на глаз";

    Вряд ли удастся выполнить в реальном мире. Но будет интересно следить за развитием.


    1. anishukserg Автор
      10.03.2026 05:15

      ро «лед» — это вы очень точно подметили. Эта аналогия даже лучше раскрывает суть, чем я планировал.

      Смотрите: когда машина тормозит на льду (экстремальная нагрузка), контракт тормозной системы не в том, чтобы остановить машину мгновенно (это физически невозможно). Контракт — это ABS. Система понимает, что сцепления нет, и начинает «отбивать» педаль, сохраняя управляемость.

      В мире СУБД «лед» — это спайк нагрузки или lock contention.

      • Обычная СУБД без контракта: Блокирует колеса. Процессы встают в очередь, память кончается (OOM), админ не может зайти в консоль. Машина летит в кювет.

      • СУБД с контрактом: Включает «ABS» (Load Shedding / Backpressure). Она говорит: «Я не могу обработать 10k запросов, я обработаю 5k, а остальным отдам ошибку сразу, не тратя ресурсы». Управляемость сохраняется.

      Вы правы, формализовать производительность в реальном мире сложно. Но для современного приложения Latency = Availability. Если база отвечает 30 секунд вместо 50 мс — для бизнеса она «лежит», даже если технически процессы живы.

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


  1. OlegIct
    10.03.2026 05:15

    Контракт БД — это проверяемые гарантии, которые либо выполняются всегда,либо система явно сообщает об отказе

    7 историй о том, как p99 "срывается"

    это не OLTP, а другой класс баз данных - Real Time. Всё, что вы описали решается в представителе этого класса - Oracle Times Ten, которая использует SQL как в Oracle Database. То есть изобретать велосипед не нужно. Проблема еще в том, что бизнесу это не нужно. В 2013 году в 11 версии TimesTen перестал развиваться, его хотели закрыть как не пользующийся спросом. Потом в ~2018 воскресили, дали версию 18 и TimesTen даже жив, но это скорее венчурная цель: вдруг где-то пригодится. Успешными были другие технологии и идеи.


    1. mentin
      10.03.2026 05:15

      Разные No/NewSQL базы тоже стабильные точечные запросы обеспечивают. А вот произвольный SQL не могут, и не видно как это было бы возможно.

      В чем-то сходно с Rust, какие-то ограниченные структуры владения объектами можно описать и он гарантирует безопасность. А вот произвольный связи как в плюсах не сделать.

      Выбор, и там и там, между универсальностью и гарантиями. В общем для обоих есть применения, но универсальность нужна чаще конечно.


      1. anishukserg Автор
        10.03.2026 05:15

        Аналогия с Rust — в точку. Но выводы я делаю ровно противоположные.

        Rust не запрещает писать сложную логику («произвольные связи»). Он запрещает писать логику, которая приведет к Undefined Behavior (segfault, data race). Да, он бьет по рукам компилятором (borrow checker), но взамен вы получаете систему, которая не падает в ран-тайме от случайного null pointer.

        Моя идея ровно в этом же: СУБД должна вести себя как компилятор Rust, а не как C++. Она не должна запрещать SQL (универсальность). Она должна запрещать Undefined Behavior в эксплуатации:

        • Запрос без LIMIT, который вычитывает всю таблицу в RAM -> OOM -> Crash.

        • Транзакцию, которая висит 4 часа и держит вакуум.

        • Full Scan по таблице в 10ТБ в интерактивном потоке.

        Это не «отказ от универсальности», это «отказ от права выстрелить себе в ногу». Мы хотим оставить SQL, но наложить на него Borrow Checker ресурсов (CPU, IO, Memory). Если запрос не укладывается в контракт — он не должен «компилироваться» (исполняться), вместо того чтобы положить прод.


        1. mentin
          10.03.2026 05:15

          На Rust нельзя описать нормально многие структуры. Нужны либо unsafe, либо проверки в рантайме. Borrow checker ограничен в том, безопасность чего он может доказать. Довольно большой класс безопасных структур он не пропустит, из-за чего в том же Rust много библиотечных классов реализовано на unsafe.

          Вы необходимо столкнетесь с чем-то подобным, буду ждать следующих статей как вы это решили.

          Тот же full scan нормален на 1 мегабайте, не ОК на допустим 10 Тб. Но где граница, и как сделать так чтобы самый важный запрос не упал, когда самая главная таблица вдруг превысила этот порог на один байт?


          1. anishukserg Автор
            10.03.2026 05:15

            «Вы правы, и это — самый "больной" вопрос архитектуры. Проблема "границы" (Threshold Problem) — это именно то, на чем ломаются простые квоты.

            Если отвечать в терминах Rust, то решение видится не в одном лишь "компиляторе" (статическом анализе запроса), а в комбинации трех механизмов:

            1. Resource-Aware Planning (Статика): Мы не просто строим план, а оцениваем его "стоимость" в конкретных единицах (IOPS, CPU-cycles, Memory pages). Если оптимизатор видит, что Full Scan на 10 ТБ потребует ресурсов, выходящих за лимит интерактивного класса нагрузки — запрос отклоняется еще до старта. Это аналог Borrow Checker.

            2. Runtime Guardrails (Динамика): Чтобы не падать из-за "лишнего байта", система должна поддерживать мягкую деградацию. Если запрос в процессе выполнения начинает потреблять больше, чем предсказал оптимизатор, он не убивается мгновенно, а переводится в "фоновый" режим с низким приоритетом (throttle) или получает сигнал на прерывание с сохранением промежуточного состояния (если это возможно).

            3. Explicit Contracts (Явность): Самое важное — граница не должна быть сюрпризом. В контракте API разработчик явно указывает: "этот запрос — интерактивный, лимит 100мс". Если таблица выросла и запрос перестал укладываться — это ошибка проектирования схемы, которую база подсвечивает сразу, а не когда сервер падает в OOM.

            В следующей статье я как раз планирую разобрать, как мы пытаемся реализовать этот "Resource Budgeting" внутри движка, чтобы избежать ситуации "вчера работало, сегодня — нет". Буду рад вашему фидбеку там!»

            «По поводу ограничений Rust — вы правы, "чистый" Borrow Checker не всесилен. Но Rust как мне кажется ценен не тем, что он запрещает сложные структуры, а тем, что он делает явными места, где гарантии могут нарушиться (через unsafe или runtime-проверки вроде RefCell).


    1. anishukserg Автор
      10.03.2026 05:15

      Про TimesTen — пример отличный, но выводы, как мне кажется, другие. TimesTen стагнировал не потому, что бизнесу не нужна предсказуемость. Он стагнировал, потому что это было дорого (Oracle), сложно и In-Memory (ограничение по объему). Бизнес не хотел платить цену «спец-решения» за обычные задачи.

      Мой тезис в том, что в 2026 году граница между RT и General Purpose OLTP стирается. Бизнесу (финтех, ритейл) критически нужен Soft Real-Time (SLA p99 < 50ms). Сейчас они решают это наймом армии DBA, которые «крутят ручки» Postgres. Я предлагаю решить это архитектурно.


      1. OlegIct
        10.03.2026 05:15

        я написал, чтобы уберечь от тупиковых идей, а не обесценить. Если идею развивает изобретатель (мало ресурсов), то обычно он не получает прибыль (первый блин комом), ее получает делающий вторую попытку. В случае компаний с ресурсами (oracle) если им не удалось, то обычно это бесперспективно.

        дорого (Oracle), сложно и In-Memory

        патенты и наработки TimesTen ушли в опцию IMDB Oracle Database, которая ест на порядок больше памяти )

        p99 нужен программистам, бизнес таких слов то не знает. Классу баз RealTime десятки лет и до сих пор граница не стерлась, а представителей баз RealTime почти нет. Но возможно, именно в 2026 граница сотрется )) Идея избавления от армии DBA была тоже у Oracle когда вводили автоматизации (AWR, ADDM). Правда спикеры Oracle были умнее и не «избавляли бизнес от DBA”, а грозились избавить DBA от рутины. )) Но кончилось всё тем, что DBA пришлось, ко всему прочему, еще и их изучать и сложность администрирования только возросла. Но, возможно, вы сможете реализовать то, что никому не удавалось или, что более реально, создать видимость для части потенциальных клиентов, соблазнив тех, кто не знает про «дешево-быстро-качественно» и «кроилово ведет к попадалову». ;) Ручки DBA не «крутят», обычно сразу всё стандартно настраивается, редко когда что-то новое и интересное обнаруживается. «Ручки крутят» там, где нет DBA или не смогли найти квалифицированного или испольщуют неподхдящие опции неподходящим образом и как следствие кажется, что PostgreSQL темный лес и непредсказуем. В реальности с PostgreSQL очень приятно работать - предсказуем, красив, приятно видеть, что все решения, применяемые сообществом идеальны. Вот даже в соседней статье хаба PostgreSQL про pgBackRest сетуют, что pgbasebackup (и startup, на него тоже бывает сетуют) однопроцессны и однопоточны. И у стороннего наблюдателя возникает впечатление, как все DBA сплошняком страдают, что они однопоточны, а «злое сообщество» никак не применяет патчи, чтобы распараллелить хотя бы резервирование.


        1. anishukserg Автор
          10.03.2026 05:15

          Олег, спасибо за развернутый ответ и предостережение. Я ценю опыт и понимаю скепсис — "очередная убийца Oracle" звучит наивно.

          Но давайте уточним пару моментов, где мы, возможно, говорим о разном:

          1. "Бизнес не знает слов p99". Бизнес знает слова "пользователи уходят, потому что чекаут крутится 10 секунд". p99 — это просто техническая метрика этого бизнес-риска. Если для вас RealTime — это только управление ядерным реактором (Hard RT), то да, граница четкая. Но я говорю про Soft Real-Time в массовом сегменте (финтех, ритейл), где "зависание" на секунды уже стоит денег.

          2. "Ручки крутят там, где нет DBA". Мой тезис ровно в этом: большинству проектов не нужен выделенный DBA, если база данных предоставляет жесткий контракт. Postgres прекрасен, но он "Permissive by default". Он по умолчанию позволит одному тяжелому запросу вымыть кэш или забить IO, из-за чего "встанут" соседние критичные транзакции. Я предлагаю подход "Restrictive by default" — когда база гарантирует изоляцию и просто не даст одной операции забрать ресурсы у других, даже если план запроса внезапно изменился.

          3. Про ресурсы и Oracle. Oracle (и TimesTen) шли путем "добавим еще фич и автоматизации поверх". Это путь усложнения. Я предлагаю путь упрощения: выкинуть всё, что мешает предсказуемости. Rust здесь не панацея всего лишь инструмент, но он позволяет писать безопасный многопоточный код дешевле, чем на C/C++ 20 лет назад.

          Я не пытаюсь сделать "Postgres, но лучше". Я делаю инструмент для конкретной ниши: когда предсказуемость важнее широты фич. И да, возможно, это "тупиковая ветвь", но проверить это можно только кодом :)