TGViewer
Катя Кондратьева Катя Кондратьева @javagymrat · 2.99K subscribers
Post #1146 2.35K
Почему PostgreSQL откатывает изменения разных строк

Вспомнила вопрос с недавнего собеса и решила разобрать в канале.

Две транзакции меняют разные счётчики, но одна из них всё равно может завершиться ошибкой. Причина в том, как база отслеживает захват объектов.

Пример: таблица counters(id PRIMARY KEY, value), без триггеров и связей с другими таблицами. Обе транзакции работают в SERIALIZABLE. Сначала выполняются оба SELECT, затем оба UPDATE и попытки COMMIT:

-- Транзакция T1
SELECT value FROM counters WHERE id = 1;
UPDATE counters SET value = value + 1 WHERE id = 1;

-- Транзакция T2
SELECT value FROM counters WHERE id = 2;
UPDATE counters SET value = value + 1 WHERE id = 2;


SERIALIZABLE обещает результат успешных транзакций как будто транзакции выполняются последовательно.

Для проверки база запоминает, кто какую область читал. Эти отметки - SIReadLock - не блокируют запись. Они помогают заметить, что чужое изменение затронуло прочитанные данные.

Пример: T1 прочитала старое значение, а T2 его изменила. Значит, в последовательном выполнении T1 должна быть раньше T2. Иначе она увидела бы новое значение. Так появляется зависимость T1 → T2.


При Seq Scan - последовательном чтении таблицы - отметка чтения ставится на всю таблицу, хотя запрос меняет одну строку.

Поэтому база учитывает две зависимости:

- T1 меняет строку 1 → задевает отметку T2 → T2 должна быть раньше T1.
- T2 меняет строку 2 → задевает отметку T1 → T1 должна быть раньше T2.

Требования противоречат друг другу. PostgreSQL отклоняет одну транзакцию с ошибкой serialization_failure, код 40001.

Это ложный конфликт: счётчики можно изменить в любом порядке, но широкая отметка связала две независимые операции.

Чтение через индекс может сузить отметку до строки/страницы и тем самым уменьшить число конфликтов. Поэтому при разборе таких откатов полезно проверить план выполнения запроса. Но полностью исключить конфликты нельзя: приложение должно уметь при ошибке 40001 повторить всю транзакцию, включая чтения.

классная статья про блокировки в постгрес

#production_case
  • 🔥 17
  • ❤ 7
More from @javagymrat
  1. Oct 4, 2026Post #1177
  2. Oct 4, 2026Post #1176
  3. Oct 4, 2026Post #1175
  4. Oct 4, 2026Post #1174
  5. Oct 4, 2026Post #1173
  6. Oct 3, 2026Ура 🥳 обновления от OpenAi Теперь снова можно взять Pro 20X подписку! Но.. теперь она буд…
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 →