Ответ
Уровни изоляции транзакций определяют степень видимости изменений, выполняемых параллельными транзакциями, и защищают от стандартных проблем конкурентного доступа. Выбор уровня — это компромисс между согласованностью данных и производительностью (параллелизмом).
Основные проблемы, от которых защищают уровни изоляции:
- Грязное чтение (Dirty Read): Чтение незафиксированных данных другой транзакции, которые могут быть откатаны.
- Неповторяющееся чтение (Non-repeatable Read): Получение разных значений одного и того же поля при повторном чтении в рамках одной транзакции из-за коммита другой транзакции.
- Фантомное чтение (Phantom Read): Появление новых или исчезновение существующих строк при повторном выполнении одного и того же запроса из-за коммита другой транзакции.
| Уровни изоляции (от меньшей к большей): | Уровень | Грязное чтение | Неповторяющееся чтение | Фантомное чтение | Механизм |
|---|---|---|---|---|---|
| Read Uncommitted | ❌ Возможно | Возможно | Возможно | Блокировок на чтение нет. | |
| Read Committed (по умолчанию в SQL Server, PostgreSQL) | ✅ Защищено | ❌ Возможно | Возможно | Блокировка изменяемой строки до коммита. | |
| Repeatable Read | ✅ Защищено | ✅ Защищено | ❌ Возможно | Блокировка читаемых и изменяемых строк. | |
| Serializable | ✅ Защищено | ✅ Защищено | ✅ Защищено | Блокировка диапазонов ключей или таблиц. |
Пример использования в C# (Entity Framework Core):
using var context = new AppDbContext();
using var transaction = await context.Database.BeginTransactionAsync(
System.Data.IsolationLevel.Serializable // Самый строгий уровень
);
try
{
// Критическая операция, требующая полной изоляции
var balance = await context.Accounts
.Where(a => a.Id == accountId)
.Select(a => a.Balance)
.FirstAsync();
if (balance >= amount)
{
// Списание средств...
await context.SaveChangesAsync();
await transaction.CommitAsync(); // Фиксация изменений
}
}
catch (Exception)
{
await transaction.RollbackAsync(); // Откат в случае ошибки
throw;
}