EF Core异步插入同表时多请求并发问题排查
并发插入突破记录数限制的原因与解决方案
核心原因:竞态条件
你遇到的问题本质是并行请求下的竞态条件,和异步操作本身无关,逐个解答你的疑问:
1. 是不是异步插入导致DbContext出现读-写-读状态?
不是。DbContext是作用域生命周期,每个请求都会拿到独立的DbContext实例。EF Core本身保证单个DbContext的操作(无论同步还是异步)都是单线程顺序执行的,不会出现混乱的读-写-读交叉状态。异步只是让处理请求的线程在等待数据库响应时可以被回收复用,不会干扰DbContext的操作顺序。
2. 是不是多请求并行读取记录数,均判定未超限后同时插入?
对,这就是问题根源。多个请求同时通过各自的DbContext读取当前表记录数,此时数据库还没来得及处理其他请求的插入操作,所以所有请求都得到“未超限”的结果,随后同时执行插入,最终总记录数就会突破限制。比如当前记录数是999,两个请求同时读到999,各自插入1条,最终就会变成1001条。
3. 是否需要手动控制读写操作的串行执行?
手动串行(比如用全局锁)能解决问题,但会严重降低并发性能,不是最优解。更好的方式是把校验+插入变成原子操作,让数据库层面来保证一致性:
- 方案一:使用带条件的原子插入
直接在数据库层面判断记录数,比如:
执行后检查影响行数,如果为0说明已达上限,拒绝请求。但要注意,INSERT INTO YourTable (Col1, Col2) VALUES (@Val1, @Val2) WHERE (SELECT COUNT(*) FROM YourTable) < 1000COUNT(*)在大表上性能较差。 - 方案二:维护独立计数器表
创建一个专门的计数器表(比如TableCounters),存储每个表的当前记录数:
插入前先更新计数器:CREATE TABLE TableCounters ( TableName VARCHAR(50) PRIMARY KEY, CurrentCount INT DEFAULT 0 )
如果该语句的影响行数为1,说明可以执行插入;否则返回上限提示。这种方式性能远优于UPDATE TableCounters SET CurrentCount = CurrentCount + 1 WHERE TableName = 'YourTable' AND CurrentCount < 1000COUNT(*),适合高并发场景。 - 方案三:事务+序列化隔离级别
如果必须保留应用层的校验逻辑,要把读记录数和插入操作放在同一个事务中,并设置隔离级别为Serializable(防止幻读):
但这种方式在高并发下容易出现锁等待,影响吞吐量,仅适合低并发场景。using var transaction = await _dbContext.Database.BeginTransactionAsync(IsolationLevel.Serializable); try { var count = await _dbContext.YourTable.CountAsync(); if (count >= 1000) { throw new InvalidOperationException("已达最大记录数"); } _dbContext.YourTable.Add(newRecord); await _dbContext.SaveChangesAsync(); await transaction.CommitAsync(); } catch { await transaction.RollbackAsync(); throw; }
EF Core与IIS如何处理并行请求?
IIS Server的处理逻辑
IIS通过线程池管理并行请求:
- 每个HTTP请求会被分配到线程池中的一个线程处理;
- 线程池会根据负载动态调整线程数量(有默认的最小/最大线程数限制);
- 当请求中执行异步操作(比如EF Core的
SaveChangesAsync)时,处理请求的线程会被释放回线程池,等数据库操作完成后,再重新分配线程继续处理后续逻辑。这种异步模型让IIS能处理更多并发请求,避免线程被长时间阻塞。
EF Core的处理逻辑
- DbContext是非线程安全的,EF Core强制单个DbContext实例只能被单线程使用,异步操作也遵循这个规则——单个DbContext的所有操作都是顺序执行的,不会出现并发;
- 因为你用的是默认的作用域生命周期,每个请求会创建独立的DbContext实例,请求结束后自动销毁。多个请求的DbContext完全独立,它们的数据库操作是并行执行的,这也是竞态条件出现的前提——每个DbContext在自己的会话中读取数据,看不到其他会话未提交的修改。
内容的提问来源于stack exchange,提问作者Thanushka
相关产品推荐
相关产品推荐

