Read Committed в PostgreSQL: какие аномалии остаются и чем их закрывают?
В PostgreSQL уровень по умолчанию — Read Committed, и он даёт меньше гарантий, чем часто думают: каждый оператор видит свой снимок, поэтому два SELECT в одной транзакции могут вернуть разные данные, а классический сценарий «прочитал остаток → посчитал → записал» теряет чужое обновление. Грязного чтения нет, но потерянное обновление и write skew есть. Закрывают их тремя способами. Атомарная запись без чтения в приложении: UPDATE ... SET balance = balance - 100 WHERE id = 1 AND balance >= 100 — сама СУБД перечитает строку под блокировкой. Явная блокировка SELECT ... FOR UPDATE, когда посчитать в SQL нельзя. Repeatable Read или Serializable, когда логика сложнее одной строки: PostgreSQL реализует их через снимки, поэтому конфликтующая транзакция не ждёт, а падает с 40001 — и приложение обязано уметь повторить её.