Ответ
Да, это классическая аномалия для уровня изоляции 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
.