TGViewer
Библиотека шарписта | C#, F#, .NET, ASP.NET Библиотека шарписта | C#, F#, .NET, ASP.NET @csharpproglib · 21.6K subscribers
Post #6413 4.03K
⚡️ Deadlock в EF Core: как предотвратить

Дедлоки редко проявляются в ходе разработки, но часто всплывают под реальной нагрузкой в продакшне. Дедлок — ситуация, когда две или более сессии базы данных блокируют друг друга, ожидая освобождения ресурсов.

В итоге 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
  • ❤ 9
  • 👍 6
More from @csharpproglib
  1. Sep 30, 2026📝 Логирование со строковой интерполяцией Логирование c интерполяцией строк один из самых…
  2. Sep 28, 2026👨‍💻 Не показывайте технические ошибки пользователям Когда приложение падает с необработа…
  3. Sep 26, 2026📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека шарписта #garbage_collector
  4. Sep 25, 2026🔐 NuGet: Microsoft меняет сертификат подписи С 23 сентября Microsoft использует новый сер…
  5. Sep 24, 2026🤩 Как поймать зависший .NET-сервис Приложение начинает тормозить, запросы зависают, а в л…
  6. Sep 23, 2026⚙️ yield return не бесплатный Итераторы выглядят просто, но работают иначе: IEnumerable<in…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →