Какой уровень изоляции транзакций допускает «грязное чтение» (Dirty Read)?

Ответ

Проблема "грязного чтения" (Dirty Read) может возникнуть только на самом низком уровне изоляции транзакций — Read Uncommitted.

Что такое "грязное чтение"?
Это ситуация, когда одна транзакция читает данные, которые были изменены другой транзакцией, но еще не зафиксированы (не был выполнен COMMIT). Если вторая транзакция в итоге будет отменена (ROLLBACK), первая транзакция будет работать с неверными, никогда не существовавшими данными.

Для сравнения, другие уровни изоляции (Read Committed, Repeatable Read, Serializable) предотвращают эту проблему, обеспечивая более высокую согласованность данных.

Пример на Go:

// Транзакция 1: Начинает изменять данные
tx1, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelReadUncommitted})
if err != nil { log.Fatal(err) }
// Уменьшаем баланс, но пока не коммитим
_, err = tx1.Exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
if err != nil { log.Fatal(err) }

// Транзакция 2: В это же время читает данные
tx2, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelReadUncommitted})
if err != nil { log.Fatal(err) }
var balance int
// Читает НЕЗАФИКСИРОВАННЫЕ данные из Транзакции 1
err = tx2.QueryRow("SELECT balance FROM accounts WHERE id = 1").Scan(&balance)
if err != nil { log.Fatal(err) }
// balance уже будет показывать новое значение, хотя tx1 еще не завершена.

// Если Транзакция 1 откатится (ROLLBACK), то Транзакция 2 будет работать с неверными, "грязными" данными.
tx1.Rollback()

Из-за риска работы с несогласованными данными, которые могут быть отменены, уровень Read Uncommitted используется крайне редко.