EF Core 小坑:DbContextPool 会引起数据库连接池连接耗尽

  • 时间:
  • 浏览:2
  • 来源:五分时时彩_五分时时彩下注平台注册_五分时时彩邀请码

DbContextPool 是 ASP.NET Core 2.1 引入的新形态学 ,时要节省创建 DbContext 实例的开销,但能够 想到其中藏着一1个多多小坑。

最近一1个多多 ASP.NET Core 项目持续运行一段时间后日志中就会出先数据库连接池达到最大连接数限制的错误:

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.
   at System.Data.Common.ADP.ExceptionWithStackTrace(Exception e)

刚刚开始了了以为是哪个地方的代码造成 DbContext 能够正常 Dispose ,但在代码中能够 找到任何相关线索。已经 人太好 能够 但会 时要怀疑的地方,唯有 DbContextPool ,于是尝试加进 DbContextPool ,结果错误就消失了。你以为是 DbContextPool 引起的,但我就纳闷的是 DbContextPool 原来就说 为了节省创建 DbContext 实例的开销,缘何反而消耗更多数据库连接,我就你你什儿 项目的负载很低,缘何将会把整个连接池都消耗殆尽呢?

今天在周会上谈了你你你什儿 怪疑问,已经 总是想到:每个 DbContext 实例总要占用一1个多多数据库连接(SqlConnection),不启用 DbContextPool 的已经 ,请求一刚刚开始了,对应 DbContext 实例就被 Dispose ,数据库连接就会被放回连接池。而使用 DbContextPool 的已经 ,请求刚刚开始了后 DbContext 不必被 Dispose 就说 被放回 DbContextPool ,DbContext 被放回属于被委托人的池中,就是因为 它对应的数据库连接不必被放回它所属的连接池。DbContextPool 中的每一1个多多 DbContext 都对应一1个多多数据库连接,DbContextPool 中每多一1个多多 DbContext ,数据库连接池中就会少一1个多多数据库连接。当你你你什儿 1个多多池的大小不一样且 DbContextPool 大于数据库连接池,疑问就来了,DbContextPool 根据自家池(假设是128)子的大小畅快地向池中填 DbContext ,浑然不顾数据库连接池的大小(假设是30),当填到第 101 个 DbContext 时就会出先中间的错误。

你你你什儿 项目中用的全是默认设置,是全是默认设置就会触发你你你什儿 疑问呢?

查看 DbContextPool 的 实现源码 发现池的默认大小限制是 128

public static IServiceCollection AddDbContextPool<TContext>(
    [NotNull] this IServiceCollection serviceCollection,
    [NotNull] Action<DbContextOptionsBuilder> optionsAction,
    int poolSize = 128)
    where TContext : DbContext
    => AddDbContextPool<TContext, TContext>(serviceCollection, optionsAction, poolSize);

查看 SqlConnention 的 实现源码 发现连接池的默认大小限制是 30

internal const int Max_Pool_Size = 30;

默认设置就会触发疑问,实人太好 在的一1个多多小坑。

知道了是因为 ,解决起来就很简单了,将 DbContextPool 的 poolSize 设置为小于数据库连接池的 Max_Pool_Size

services.AddDbContextPool<JobDb>(option =>
    option.UseSqlServer(Configuration.DbConnectionStr()), 
    poolSize: 64);