Какой уровень изоляции предотвращает Dirty Write?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Уровни изоляции транзакций и Dirty Write
Dirty Write — это явление, когда одна транзакция перезаписывает данные, которые ещё не были закоммичены другой транзакцией. Это одна из самых опасных аномалий в многопользовательских СУБД.
Что такое Dirty Write?
Транзакция 1 выполняет WRITE x = 100, потом Транзакция 2 выполняет WRITE x = 200 (грязная запись). Затем Транзакция 1 выполняет ROLLBACK, и x возвращается к прежнему значению. Но Транзакция 2 уже закоммитила значение 100, а не 200.
Уровни изоляции ACID
SQL стандарт определяет четыре уровня изоляции. Dirty Write предотвращается на ВСЕ уровнях, начиная с самого слабого:
1. READ UNCOMMITTED
// Может прочитать грязные (незакоммиченные) данные
statement.execute("UPDATE accounts SET balance = 500 WHERE id = 1");
ResultSet rs = statement.executeQuery("SELECT balance FROM accounts WHERE id = 1");
Допускает Dirty Read и Non-Repeatable Read, но Dirty Write предотвращается.
2. READ COMMITTED
Connection conn = DriverManager.getConnection(url, user, pass);
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
Предотвращает Dirty Write и Dirty Read. Это стандартный уровень в PostgreSQL.
3. REPEATABLE READ
conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
Предотвращает Dirty Write, Dirty Read и Non-Repeatable Read. Допускает Phantom Read.
4. SERIALIZABLE
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
Предотвращает все аномалии, включая Phantom Read. Максимальная безопасность, минимальная производительность.
Почему Dirty Write предотвращается везде?
Базовая проблема Dirty Write — это конфликт записи-записи (Write-Write conflict). Все СУБД решают это через Write Locks на уровне ядра:
Transaction 1: LOCK X → WRITE X = 100
Transaction 2: LOCK X (waiting...) → WAIT
Transaction 1: COMMIT, UNLOCK X
Transaction 2: LOCK X (success) → WRITE X = 200 → COMMIT
Поэтому даже на READ UNCOMMITTED две транзакции не могут одновременно писать в один и тот же объект.
Сравнительная таблица аномалий
| Уровень | Dirty Read | Non-Rep Read | Phantom Read |
|---|---|---|---|
| READ UNCOMMITTED | ✗ | ✗ | ✗ |
| READ COMMITTED | ✓ | ✗ | ✗ |
| REPEATABLE READ | ✓ | ✓ | ✗ |
| SERIALIZABLE | ✓ | ✓ | ✓ |
Практический пример
public class TransactionDemo {
public static void main(String[] args) throws SQLException {
Connection conn = DriverManager.getConnection(url);
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
try {
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
stmt.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
stmt.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
conn.commit(); // Грязная запись невозможна
} catch (SQLException e) {
conn.rollback();
} finally {
conn.close();
}
}
}
Ответ
Dirty Write предотвращается на ВСЕ уровнях изоляции, включая READ UNCOMMITTED. Это происходит благодаря Write Locks на уровне ядра СУБД, которые не позволяют двум транзакциям одновременно модифицировать один и тот же объект.