从.Net Core 3.1升级到.Net 5后EF Core插入操作偶发缓慢求助
问题根因
该问题是EF Core 5.0.10配套依赖的组件存在已知性能缺陷导致,核心原因有两个:
- EF Core 5.x相对3.1版本修改了隐式事务逻辑:3.1版本针对单条数据变更会默认使用数据库自动提交模式,不会显式开启事务;而5.x版本无论变更条数多少,都会默认开启显式事务,新增了事务启动的开销。
- 配套使用的
Microsoft.Data.SqlClient2.x版本在Linux容器环境下存在连接池复用缺陷:当连接池中长时间闲置的连接被复用时,开启事务环节会额外执行冗余的连接状态校验,和MSSQL 2017集群交互时会产生数百毫秒的延迟,这就是你观测到10%请求变慢的核心原因——只有命中闲置连接复用的请求才会出现延迟,其余使用活跃连接的请求性能不受影响。
修复方案
你可以任选以下方案解决问题:
- 升级依赖组件:直接将
Microsoft.Data.SqlClient升级到2.1.x最新稳定版,或升级到3.x及以上版本,该连接池复用缺陷已在后续版本修复;也可同步将EF Core升级到5.0.17(5.x分支最终补丁版),修复更多已知性能问题。 - 调整连接字符串配置:在MSSQL连接字符串中添加参数
PoolBlockingPeriod=NeverBlock,该参数专门针对Linux环境下的连接池阻塞问题做了优化,无需修改代码即可大幅降低闲置连接复用的延迟。 - 针对日志插入场景禁用隐式事务:日志写入不需要强事务保证,可在配置DbContext时关闭隐式事务:
optionsBuilder.UseSqlServer(连接字符串, opt => opt.DisableAmbientTransactions());
也可在写入日志时使用更低隔离级别的事务减少开销:
using var transaction = _dbContext.Database.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted); await _dbContext.SaveChangesAsync(); await transaction.CommitAsync();
- 调整连接池生命周期:如果不方便升级组件,可在连接字符串中添加
Connection Lifetime=300,让闲置超过5分钟的连接自动释放,减少命中闲置缺陷连接的概率。
内容的提问来源于stack exchange,提问作者Brian Eilskov
相关产品推荐
相关产品推荐

