TGViewer
Женя Янченко Женя Янченко @jane_yanchenko · 5.51K subscribers
Post #104 1.47K
Продолжаем разбирать главу кабанчика («Высоконагруженные приложения» Мартина Клепманна) про транзакции. Ссылки на конспекты предыдущих глав есть в закрепе.

Асимметрия записи и фантомы

Разобраться с этими аномалиями нам помогут два примера. В первом примере у нас график врачей в больнице. Бизнес-требование: на дежурстве должен находиться как минимум один врач. Транзакции и состояние БД в случае, когда два дежурных врача одновременно запросили отгул, показаны на первой картинке к посту.

Во втором примере — бронирование переговорных. Бизнес-требование: нельзя забронировать переговорную на одно и то же время дважды. Поэтому при запросе бронирования мы сначала проверяем, нет ли уже бронирований на пересекающийся промежуток времени. Если нет, то можно создавать свое бронирование. Транзакции и состояние БД в случае попытки одновременного бронирования показаны на второй картинке к посту.

Возникшая аномалия называется асимметрией записи (write skew).

Схема возникновения асимметрии записи:

👀 транзакция читает данные,
🤔 принимает на основе прочитанного решение о дальнейших действиях
✍️ и выполняет запись в БД.

🤨 Однако на момент выполнения записи исходные условия, на основе которых принималось решение, уже не соответствуют действительности.

Это не «грязная» запись и не потеря обновления, поскольку транзакции обновляют два различных объекта (разные графики дежурств, разные записи в таблице бронирования).

В прошлом посте мы рассмотрели способы предотвращения потери обновлений. В случае асимметрии записи возможностей меньше:

🔴 Атомарные однообъектные операции (SET value = value + 10) не помогут, поскольку в транзакции участвует несколько объектов.

🟡 В некоторых случаях могут помочь ограничения целостности базы (например, уникальность, внешние ключи или ограничения на конкретных значений). Однако в случае дежурных врачей понадобилось бы ограничение, налагаемое на несколько объектов. В большинстве баз нет встроенной поддержки подобных ограничений, но их можно реализовать с помощью триггеров или материализованных представлений.
‰
🟢 Явная блокировка результатов SELECT FOR UPDATE может помочь в тех случаях, когда SELECT возвращает какие-то данные.

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

🟡 Автоматическое обнаружение базой данных

Эффект, при котором операция записи в одной транзакции меняет результат запроса на поиск в другой, называется фантомом (phantom).

Кратко схему аномалии фантомного чтения можно описать так:

➡️Первая транзакция делает SELECT по какому-то условию
➡️Другая транзакция делает INSERT/UPDATE/DELETE, который влияет на выборку из 1-го шага
➡️Первая транзакция делает SELECT и видит отличающийся результат по сравнению с первым чтением

Изоляция снимков состояния (уровень Repeatable Read в PostgreSQL) предотвращает фантомные чтения.

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

🟢 Материализация конфликтов — это создание в базе объектов, на которые можно было бы повесить блокировку SELECT FOR UPDATE для превращения фантома в конфликт.

Например, в случае с бронированием переговорных можно создать отдельную таблицу, в которой каждая строка будет соответствовать связке переговорная + отрезок времени 15 минут. Тогда транзакция перед созданием бронирования могла бы блокировать (SELECT FOR UPDATE) в этой таблице строки, соответствующие нужной переговорной и отрезкам времени. После установки блокировок можно сделать проверку и вставить новую бронь, как и раньше. Обратите внимание: сама дополнительная таблица не хранит информацию о бронировании — она нужна только для блокировок.

Материализация конфликтов непроста, да и перенос управления конкурентным доступом в модель данных приложения выглядит не очень красиво. Поэтому ее рассматривают, когда не подходит изоляция уровня сериализуемости.

#кабанчик #сисдиз
  • 👍 9
  • 🔥 7
  • ❤ 2
  • 😁 1
More from @jane_yanchenko
  1. Sep 25, 2026В прошлой жизни, когда я была менеджером проектов, одним из первых мест работы у меня был…
  2. Sep 23, 2026Куда пропало обращение - развязка В прошлом посте у нас загадочно пропало обращение 58122.…
  3. Sep 23, 2026Куда пропало обращение Однажды от руководителя техподдержки пришло письмо, суть которого с…
  4. Sep 21, 2026🔗 Подборка постов про Кафку Как обещала на стриме, собрала посты про Кафку в удобное огла…
  5. Sep 21, 2026🎞 Готова запись стрима про Кафку: https://youtu.be/2aRKsD-MWDA Большое спасибо всем, кто…
  6. Sep 16, 2026Сегодня стрим по Кафке в 19:00 Планируем не в формате доклада, а в формате вопрос-ответ, ч…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →