System.InvalidOperationException: 超时已过期。在从池中获取连接之前超时时间已过。这可能是因为所有池化连接均在使用中且已达到最大池大小。
System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
ID: dotnet/ef-core-connection-timeout-pool-exhaustion
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| Entity Framework Core 7.0 | active | — | — | — |
| Entity Framework Core 8.0 | active | — | — | — |
| Microsoft.Data.SqlClient 5.1.0 | active | — | — | — |
根因分析
连接池耗尽发生在数据库连接未正确释放时,导致所有池化连接保持打开状态,新请求无限期等待。
English
Connection pool exhaustion occurs when database connections are not properly disposed, causing all pooled connections to remain open and new requests to wait indefinitely.
官方文档
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling解决方案
-
确保所有 DbContext 实例通过使用 'using' 语句或依赖注入作用域生命周期正确释放。例如:'using (var context = new MyDbContext()) { ... }' 或在 DI 中注册为作用域:'services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Scoped)'。 -
如果使用异步操作,确保每个异步调用都被 await 以避免未完成任务导致连接泄漏。使用 'await using' 进行异步释放:'await using var context = new MyDbContext();'
-
临时增加连接字符串中的 Max Pool Size 和 Connection Timeout 作为短期缓解措施,同时修复根本原因:'Server=myServer;Database=myDB;Max Pool Size=200;Connection Timeout=30;'
无效尝试
常见但无效的做法:
-
75% 失败
Increasing Max Pool Size in the connection string only delays the issue; it does not fix the underlying leak.
-
90% 失败
Restarting the application temporarily clears the pool but connections will leak again if disposal is not fixed.
-
80% 失败
Adding retry logic without fixing disposal causes the same timeout to repeat, wasting resources and slowing response.