Ответ
Уровень изоляции транзакции определяет, насколько изменения, сделанные в одной транзакции, видны другим параллельным транзакциям, и как они защищены от взаимного влияния. Повышение уровня изоляции усиливает целостность данных, но снижает производительность и параллелизм из-за блокировок.
Побочные эффекты (аномалии), которые могут проявиться при НИЗКИХ уровнях изоляции:
-
Dirty Read(Грязное чтение):- Что это: Транзакция читает незафиксированные изменения другой транзакции. Если та транзакция откатится, первая прочитает «мусорные» данные.
- Когда возникает: Уровень
READ UNCOMMITTED. - Пример: Транзакция A видит новые цены, которые транзакция B еще не подтвердила. B откатывается, но A уже работала с несуществующими данными.
-
Non-Repeatable Read(Неповторяющееся чтение):- Что это: В рамках одной транзакции два одинаковых запроса возвращают разные данные для одних и тех же строк, потому что другая транзакция изменила и зафиксировала эти строки между запросами.
- Когда возникает: Уровень
READ COMMITTED(стандартный для многих СУБД). - Пример: Транзакция A дважды читает баланс счета. Между чтениями транзакция B снимает деньги и коммитится. Второе чтение в A покажет новый, уменьшенный баланс.
-
Phantom Read(Фантомное чтение):- Что это: Похоже на неповторяющееся чтение, но касается появления или исчезновения строк (наборов данных), а не изменения существующих. Два одинаковых запроса возвращают разное количество строк.
- Когда возникает: Уровень
REPEATABLE READ. - Пример: Транзакция A выбирает все заказы за сегодня. Транзакция B создает новый заказ и коммитится. Если A повторит запрос, она увидит «фантомную» новую строку.
Побочные эффекты при ВЫСОКИХ уровнях изоляции:
Increased Locking & Contention(Рост блокировок и конфликтов):- Что это: Уровень
SERIALIZABLEдля предотвращения всех аномалий использует строгие блокировки (например, блокировки диапазонов ключей). Это приводит к:- Увеличению времени ожидания (
deadlocks). - Снижению пропускной способности (throughput).
- Риску взаимоблокировок (deadlock), которые СУБД вынуждена разрешать, откатывая одну из транзакций.
- Увеличению времени ожидания (
- Что это: Уровень
Практический пример выбора уровня в коде (C# ADO.NET):
using (var connection = new SqlConnection(connectionString))
{
await connection.OpenAsync();
// Выбор уровня изоляции — компромисс между целостностью и производительностью
using (var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted))
{
try
{
var command = connection.CreateCommand();
command.Transaction = transaction;
command.CommandText = "UPDATE Accounts SET Balance = Balance - 100 WHERE Id = 1";
await command.ExecuteNonQueryAsync();
// На уровне ReadCommitted здесь невозможно грязное чтение,
// но возможно неповторяющееся чтение.
transaction.Commit(); // Фиксация изменений
}
catch
{
transaction.Rollback(); // Откат в случае ошибки
throw;
}
}
}
Вывод: Выбор уровня изоляции — это баланс между консистентностью данных (требованиями бизнес-логики) и производительностью приложения. Чаще всего используется Read Committed как разумный компромисс.