База может показать два разных состояния даже внутри одной транзакции. Объясняем, какие гарантии видимости дают уровни изоляции.
Откуда берутся два разных результата
Представим условную складскую систему. Сотрудник проверил остаток и увидел двести упаковок. Пока он изучал другие сведения, коллега подтвердил выдачу двадцати упаковок. При повторном чтении первый сотрудник увидел сто восемьдесят. Числа различаются, хотя он сам ничего не менял.
В многопользовательской базе это может быть нормальным следствием выбранного режима работы. Чтобы понять ситуацию, надо уточнить, какое состояние доступно читателю и какие чужие изменения он вправе увидеть. Эти правила связаны с уровнем изоляции транзакции — группы действий, которые база рассматривает как единую работу.
Зачем нужны разные версии состояния
Система может хранить сведения о нескольких версиях записи и выбирать подходящую для чтения. Такой подход называют многоверсионностью. Он позволяет читателю работать с определённым состоянием, пока другие участники изменяют данные. Общий принцип описан в введении PostgreSQL в управление конкурентным доступом.
Снимок состояния не обязательно означает отдельную физическую копию всей базы. Это правила видимости версий. Поэтому вопрос «я всё ещё работаю с той же базой?» не объясняет различие результатов. Нужен другой вопрос: к какому моменту относится состояние, которое показали именно этому чтению?
Снимок на каждое чтение
В режиме Read Committed, который можно описать как чтение подтверждённых изменений, обычное чтение в PostgreSQL видит состояние на начало своего запроса. Следующее чтение может получить новый снимок и увидеть изменения, которые за это время подтвердили другие участники. Это предусмотрено правилами изоляции PostgreSQL.
Поэтому объединение двух чтений в одну транзакцию само по себе не гарантирует одинаковый результат. В условном примере оба остатка могут быть корректными, но относиться к разным моментам. Если человеку нужны свежие сведения, это полезно. Если он собирает взаимосвязанные части одного отчёта, различие моментов уже нужно учитывать.
Когда важно повторять чтение одного состояния
Режим Repeatable Read предназначен для более устойчивого представления данных в рамках транзакции. В PostgreSQL обычные чтения ориентируются на снимок, зафиксированный при начале работы с данными внутри неё, и не подхватывают последующие чужие подтверждённые изменения. Собственные изменения транзакции при этом учитываются.
Однако детали зависят от системы и вида операции. В документации MySQL InnoDB отдельно разграничены обычные согласованные чтения и операции, которым требуется актуальное состояние и блокировка. Поэтому нельзя считать одно название режима исчерпывающим описанием поведения любой базы.
Более строгий режим тоже имеет цену
Режим Serializable требует, чтобы результаты успешно завершённых транзакций согласовывались с возможным выполнением работ по очереди. Это не означает, что система обязательно буквально обслуживает всех по одному. Она может обнаружить конфликт и потребовать повторить работу. Это следует из описания режимов работы PostgreSQL. Такой повтор — предусмотренный сценарий, а не повод молча использовать результат неудавшейся попытки.
Задача команды — выбирать гарантии под смысл операции. Для просмотра справочной информации допустим один режим, для согласованного расчёта могут требоваться другие условия. Установка самого строгого уровня без понимания повторов, нагрузки и поведения приложения не является готовым решением всех ошибок.
Как разбирать расхождение в отчёте
Сначала стоит выяснить, какие операции выполнялись, были ли они в одной транзакции, какой режим использовался и кто менял записи между чтениями. Затем уточнить, нужны ли данные «на один момент» или наиболее свежий доступный результат. Это разные требования, которые иногда ошибочно смешивают.
В условном складском отчёте можно явно определить момент, к которому относятся остатки и выдачи. Тогда двести и сто восемьдесят перестают выглядеть загадочным противоречием. Смысл уровней изоляции именно в том, чтобы договориться о видимом состоянии, а не просто добиться одинаковых цифр при любой повторной проверке.
Как перейти к практике
Если хотите разбирать подобные задачи системно, посмотрите программу SQL инженер. Важно учиться связывать устройство системы с потребностями пользователей и проверять ограничения выбранного подхода.


