Дедлоки редко проявляются в ходе разработки, но часто всплывают под реальной нагрузкой в продакшне. Дедлок — ситуация, когда две или более сессии базы данных блокируют друг друга, ожидая освобождения ресурсов.
В итоге SQL Server прерывает одну из транзакций:
SqlException: Transaction (Process ID xx) was deadlocked on resources...
Пример простого дедлока: два контекста одновременно меняют одну строку и пытаются сохранить изменения. Один запрос блокирует строку, второй вызывает дедлок.
await using var context1 = new AppDbContext();
await using var context2 = new AppDbContext();
var order1 = await context1.Orders.FindAsync(1);
var order2 = await context2.Orders.FindAsync(1);
order1.Status = "Paid";
order2.Status = "Shipped";
await context1.SaveChangesAsync(); // Блокирует строку
await context2.SaveChangesAsync(); // Возможен deadlock
Стратегии предотвращения
• Короткие транзакции
Минимизируйте работу внутри транзакции:
await using var tx = await context.Database.BeginTransactionAsync();
var order = await context.Orders.FindAsync(orderId);
order.Status = "Paid";
await context.SaveChangesAsync();
await tx.CommitAsync();
Избегайте сетевых вызовов и посторонних запросов перед коммитом.
• Правильные индексы
Отсутствие индексов приводит к сканированию таблиц и длительным блокировкам. Используйте SQL Profiler для мониторинга.
• Оптимальный уровень изоляции
ReadCommitted обычно достаточен для большинства операций:
await using var tx = await context.Database.BeginTransactionAsync(
IsolationLevel.ReadCommitted);
• Логика повторов
Используйте встроенную политику retry в EF Core:
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(connectionString, sql =>
sql.EnableRetryOnFailure(
maxRetryCount: 3,
maxRetryDelay: TimeSpan.FromSeconds(5),
errorNumbersToAdd: null)));
• RowVersion для контроля конкурентности
public class Order
{
public int Id { get; set; }
public string Status { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
EF Core выбросит
DbUpdateConcurrencyException при конфликте изменений.Дедлоки не баги, а следствие паттернов конкурентного доступа.
🐸 Библиотека шарписта
#sharp_view