Почему я должен использовать уровень изоляции Repeatable Read (или выше), если мне нужно прочитать версию во второй раз? - PullRequest
2 голосов
/ 15 октября 2019

Я прочитал главу книги Мартина Фаулера Optimistic Offline Lock

Автор описывает следующий пример (если я правильно понял):

Есть 2 предмета: Order и Client,Участвуют 2 транзакции (бизнес):

  1. Первая транзакция вычисляет сумму налогов заказа. Сумма налогов зависит от пунктов заказа и адреса клиента

  2. Вторая транзакция обновляет адрес клиента

Проблема здесь в том, что если адрес client будетизменить при расчете суммы налогов order результат может быть противоречивым. Авторы предложили 2 решения, основанные на оптимистичной автономной блокировке. Один из них - проверка версий order и client в начале транзакции и проверка версий order и client в конце транзакции. Но здесь автор предупреждает, что мы должны использовать уровень изоляции REPEATABLE READ или выше, чтобы иметь возможность читать версии во второй раз. Это причина моего вопроса. Как я понимаю, если я прочту какую-либо строку во второй раз, я получу тот же результат, потому что при использовании этого уровня изоляции БД блокирует все строки, которые мы читали ранее.

Пожалуйста, объясните мне идею автора.

1 Ответ

0 голосов
/ 15 октября 2019

БД блокирует все строки, которые мы читали раньше, только если это требуется. REPEATABLE READ уровень изоляции - минимальный уровень, требующий его. Из документов PG:

Read Committed - уровень изоляции по умолчанию в PostgreSQL. Когда транзакция использует этот уровень изоляции, запрос SELECT (без предложения FOR UPDATE / SHARE) видит только данные, зафиксированные до начала запроса;он никогда не видит ни незафиксированные данные, ни изменения, зафиксированные во время выполнения запроса параллельными транзакциями. По сути, запрос SELECT видит снимок базы данных с момента начала выполнения запроса. Однако SELECT видит результаты предыдущих обновлений, выполненных в пределах его собственной транзакции, даже если они еще не зафиксированы. Также обратите внимание, что две последовательные команды SELECT могут видеть разные данные, даже если они находятся в одной транзакции, если другие транзакции фиксируют изменения после запуска первого SELECT и до запуска второй SELECT.

Так что в случаевы работаете с REPEATABLE READ + уровнем изоляции, обновление будет выполнено успешно (версия «стабильная»), но в случае, если другая транзакция изменила поле версии, ваша транзакция не будет зафиксирована.

В случае запуска с READ COMMITTED уровень изоляции и другая транзакция изменяет поле версии до того, как вы это сделаете, ваш UPDATE ничего не обновит (executeUpdate вернет 0). Таким образом, вы можете проверить это и действовать соответствующим образом.

Итог, можно использовать обе опции, но поведение не одинаково, и ваш код должен вести себя по-разному. Если вы используете ORM, внимательно проверьте его поведение.

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