То, что вы описали в своем посте, является распространенной ситуацией в многопользовательских системах.Различные сеансы одновременно запускают транзакции с использованием одних и тех же таблиц и одинаковых строк.Здесь есть две проблемы:
- Что происходит, если Сессия C читает запись после того, как Сессия A обновила ее, но до того, как Сессия A совершила свою торговую операцию ?
- Что произойдет, если сеанс C обновит ту же запись, которую обновил сеанс A, но не зафиксировано ?
(Ваш сценарий иллюстрирует только первую из этих проблем).
Ответ на первый вопрос - уровень ioslation.Это определение видимости незафиксированных транзакций между сеансами.Стандарт ANSI определяет четыре уровня :
- SERIALIZABLE: никаких изменений из другого сеанса не видно.
- REPEATABLE READ: фантомное чтение разрешено, то есть то же самоеВыполненный дважды запрос может вернуть разные результаты.
- READ COMMITTED: видны только изменения, зафиксированные в другом сеансе.
- READ UNCOMMITTED: diryt readsallowed, то есть незафиксированные изменения из одного сеанса видныв другом.
Различные разновидности или базы данных реализуют их по-разному, и не все базы данных поддерживают все из них.Например, Oracle поддерживает только READ COMMITTED и SERIALIZABLE, а также реализует SERIALIZABLE в качестве моментального снимка (т.е. это транзакция только для чтения).Однако для предотвращения неповторяющихся операций чтения в транзакциях READ COMMITTED используется многофакторный контроль параллелизма.
Итак, возвращаясь к вашему вопросу, вы получите ответ: установите соответствующий уровень изоляции.Какой соответствующий уровень зависит от того, какие уровни поддерживает ваша база данных и какое поведение вы хотите получить.Возможно, вы хотите READ COMMITTED или SERIALIZABLE, то есть вы хотите, чтобы ваши транзакции продолжались на основе значений данных, согласующихся с началом транзакции.
Что касается другого вопроса, ответ проще: транзакции должныПеред их обновлением создайте блокировки для таблиц или, желательно, только для нужных строк.Это гарантирует, что транзакция может продолжить изменять эти значения, не вызывая взаимоблокировку.Это называется пессимистической блокировкой.Это невозможно в приложениях, которые используют пул соединений (то есть в большинстве веб-приложений), и ситуация там гораздо сложнее.