You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core多线程插入SQL Server遇死锁,求更优解决办法

解决高并发下SQL Server自增主键插入死锁及性能问题

核心问题分析

你遇到的死锁本质是高并发下,EF Core默认的「INSERT + SELECT scope_identity()」两次请求导致的锁竞争:插入操作持有行锁,后续查询操作又需要获取相关锁,多个线程交叉执行时容易形成死锁。而你之前添加的手动事务扩大了锁的持有范围,是性能暴跌5倍的主要原因。

优化方案

1. 移除多余的手动事务,保留重试策略

EF Core的SaveChangesAsync()本身就是原子性操作(默认在一个事务内执行),额外套的手动事务完全没必要,反而增加了事务开启、提交/回滚的开销。修改后的代码如下:

public async Task InsertLogApi(LogApi logApi)
{
    var executionStrategy = _context.Database.CreateExecutionStrategy();
    await executionStrategy.ExecuteAsync(async () =>
    {
        _context.Add(logApi);
        await _context.SaveChangesAsync();
    });
}

这样既保留了死锁后的重试能力,又消除了手动事务带来的额外性能损耗。

2. 让EF Core合并INSERT与ID查询为单条SQL

部分版本的EF Core会分开执行INSERT和SELECT获取自增ID,你可以通过配置让EF使用OUTPUT子句一次性完成插入并返回ID,减少一次数据库请求,同时缩短锁持有时间。

在DbContext的OnModelCreating方法中配置实体主键:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<LogApi>()
        .Property(e => e.Id)
        .UseIdentityColumn(); // 确保使用自增列并启用OUTPUT返回ID
}

配置后EF会生成类似这样的SQL:

INSERT INTO [LogApi] (...)
VALUES (@p0, @p1, ...)
OUTPUT INSERTED.[Id];

将两次请求合并为一次,从根源上减少锁竞争的概率。

3. 批量插入替代单条插入

高并发场景下,单条插入的性能瓶颈非常明显。可以通过批量收集请求(比如用内存队列攒N条数据,或按时间窗口批量),再用AddRange批量插入:

public async Task InsertLogApiBatch(List<LogApi> logApiList)
{
    var executionStrategy = _context.Database.CreateExecutionStrategy();
    await executionStrategy.ExecuteAsync(async () =>
    {
        _context.AddRange(logApiList);
        await _context.SaveChangesAsync();
    });
}

批量插入不仅减少了数据库请求次数,EF Core还会优化生成批量INSERT语句,同时通过OUTPUT一次性返回所有自增ID,锁的持有时间也会大幅缩短,死锁概率和性能开销都会显著降低。

4. 开启数据库的READ_COMMITTED_SNAPSHOT隔离级别

在SQL Server中执行以下语句开启快照隔离:

ALTER DATABASE [你的数据库名] SET READ_COMMITTED_SNAPSHOT ON;

开启后,默认的ReadCommitted隔离级别下,读操作会使用数据快照而非加共享锁,彻底避免读写操作之间的锁竞争,从数据库层面解决死锁问题。这个设置对现有业务无侵入,是高并发写入场景的常用优化手段。

优先级建议

优先尝试方案1+方案2,这两个改动最小,能快速恢复性能并降低死锁概率;如果并发量极高,再引入方案3的批量插入;方案4作为兜底的数据库层面优化,可以长期生效。

内容的提问来源于stack exchange,提问作者Zaldrize

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 09:43:16