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