Ответ
Да, это классическая аномалия для уровня изоляции Read Committed
.
Что гарантирует
Read Committed
: Этот уровень изоляции защищает только от "грязного чтения" (Dirty Read). То есть одна транзакция не может прочитать данные, которые были изменены другой транзакцией, но ещё не зафиксированы (COMMIT
).Что такое
Non-Repeatable Read
: Эта аномалия возникает, когда в рамках одной транзакции два последовательных чтения одной и той же строки возвращают разные результаты. Это происходит потому, что между этими чтениями другая транзакция успела изменить эти данные и зафиксировать свои изменения.
Пример в виде временной шкалы:
Представим, что на счете (id=1) изначально 100.
Время | Транзакция 1 (Ваша) | Транзакция 2 (Параллельная) |
---|---|---|
T1 | BEGIN; | |
T2 | SELECT balance FROM accounts WHERE id = 1; | |
-- Возвращает 100 | ||
T3 | BEGIN; | |
T4 | UPDATE accounts SET balance = 200 WHERE id = 1; | |
T5 | COMMIT; | |
T6 | SELECT balance FROM accounts WHERE id = 1; | |
-- Возвращает 200! | ||
T7 | COMMIT; |
В момент T6 Транзакция 1 получает другой результат для того же запроса, что и в T2. Это и есть "неповторяющееся чтение".
Для предотвращения этой аномалии необходимо использовать более строгий уровень изоляции, например, Repeatable Read
.