← Назад к вопросам

Какой уровень изолированной транзакции используется по умолчанию?

2.2 Middle🔥 191 комментариев
#Entity Framework и ORM#Базы данных и SQL

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Уровень изоляции транзакций по умолчанию в C#

По умолчанию в Microsoft SQL Server используется уровень изоляции READ COMMITTED. Это поведение распространяется и на ADO.NET, и на Entity Framework Core, когда вы не указываете уровень изоляции явно.

Почему READ COMMITTED является уровнем по умолчанию?

Этот уровень представляет баланс между целостностью данных и производительностью:

  • Предотвращает "грязное чтение" (Dirty Read): транзакция видит только зафиксированные данные других транзакций.
  • Допускает "неповторяемое чтение" (Non-Repeatable Read) и "фантомное чтение" (Phantom Read).
  • Обеспечивает приемлемую конкурентность, блокируя только читаемые строки на время операции.

Как это работает в коде?

Ниже пример явного указания уровня изоляции в ADO.NET:

using (var connection = new SqlConnection(connectionString))
{
    await connection.OpenAsync();
    
    // Явное указание уровня изоляции (необязательно, т.к. READ COMMITTED используется по умолчанию)
    using (var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted))
    {
        try
        {
            using (var command = new SqlCommand("UPDATE Users SET Balance = Balance - 100 WHERE Id = 1", connection, transaction))
            {
                await command.ExecuteNonQueryAsync();
            }
            
            await transaction.CommitAsync();
        }
        catch
        {
            await transaction.RollbackAsync();
            throw;
        }
    }
}

В Entity Framework Core уровень изоляции также можно задать явно:

await using var context = new AppDbContext();
await using var transaction = await context.Database.BeginTransactionAsync(IsolationLevel.ReadCommitted);

try
{
    var user = await context.Users.FirstAsync(u => u.Id == 1);
    user.Balance -= 100;
    await context.SaveChangesAsync();
    
    await transaction.CommitAsync();
}
catch
{
    await transaction.RollbackAsync();
    throw;
}

Другие уровни изоляции

SQL Server поддерживает несколько уровней (от менее строгих к более строгим):

  1. READ UNCOMMITTED:

    • Допускает грязное, неповторяемое и фантомное чтение
    • Использует NOLOCK на уровне таблицы
  2. READ COMMITTED (по умолчанию):

    • Запрещает грязное чтение
    • Допускает остальные аномалии
    • Может приводить к блокировкам
  3. REPEATABLE READ:

    • Запрещает грязное и неповторяемое чтение
    • Допускает фантомное чтение
    • Обеспечивает согласованность данных внутри транзакции
  4. SERIALIZABLE:

    • Полная изоляция, запрещает все аномалии
    • Наименьшая производительность
    • Использует диапазонные блокировки
  5. SNAPSHOTREAD_COMMITTED_SNAPSHON):

    • Версионная модель изоляции
    • Чтение из снапшота данных на момент начала транзакции
    • Минимизирует блокировки за счет использования tempdb

Рекомендации по использованию

  • Не меняйте уровень изоляции без необходимости – каждый более строгий уровень снижает производительность
  • Для высоконагруженных систем рассмотрите READ_COMMITTED_SNAPSHOT:
    ALTER DATABASE YourDatabase SET READ_COMMITTED_SNAPSHOT ON;
    
  • Используйте явное указание уровня изоляции только при понимании последствий для бизнес-логики

Важное замечание

Уровень изоляции READ COMMITTED реализован через блокировки в SQL Server. Читающие операции блокируют данные от изменения до завершения текущей транзакции, что может приводить к дедлокам в сложных сценариях. Альтернатива – включение READ_COMMITTED_SNAPSHOT на уровне базы данных, который использует версионирование строк вместо блокировок.

Вывод: Понимание уровня изоляции по умолчанию критично для проектирования корректной конкурентной обработки данных в enterprise-приложениях. Уровень READ COMMITTED обеспечивает базовую гарантию целостности без значительных потерь производительности.