DbContextPool 是 ASP.NET Core 2.1 引入的新特性,可以节省创建 DbContext 实例的开销,但没有想到其中藏着一个小坑。

最近有一个 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 实例都会占用一个数据库连接(SqlConnection),不启用 DbContextPool 的时候,请求一结束,对应 DbContext 实例就被 Dispose ,数据库连接就会被放回连接池。而使用 DbContextPool 的时候,请求结束后 DbContext 不会被 Dispose 而是被放回 DbContextPool ,DbContext 被放回属于自己的池中,就意味它对应的数据库连接不会被放回它所属的连接池。DbContextPool 中的每一个 DbContext 都对应一个数据库连接,DbContextPool 中每多一个 DbContext ,数据库连接池中就会少一个数据库连接。当这两个池的大小不一样且 DbContextPool 大于数据库连接池,问题就来了,DbContextPool 根据自家池(假设是128)子的大小畅快地向池中填 DbContext ,浑然不顾数据库连接池的大小(假设是100),当填到第 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 的 实现源码 发现连接池的默认大小限制是 100

internal const int Max_Pool_Size = 100;

默认设置就会触发问题,实实在在的一个小坑。

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

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

EF Core 小坑:DbContextPool 会引起数据库连接池连接耗尽的更多相关文章

  1. Java使用数据库连接池连接Oracle数据库

    第一步:导入tomcat\lib 下的一个tomcat-dbcp.jar包第二步:在web\META-INF下新建一个context.xml文件,文件内容如下: <?xml version=&q ...

  2. 解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题

    解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题 最近有个问题非常讨厌,我们的工程中使用自己的连接池连接mysql数据库,可mysql数据库每隔8小时就会自动断开所有链接, ...

  3. net core 小坑杂记之配置文件读取(不定期更新)

    其实很早就想写了,原想等积累差不多了再写的,但是发现遇到一个当时记下效果会比较好,所以就不定期更新这个系列了,后面获取会整个整理一下. 此篇记载net core入门时踩的一些坑,网上教程太少了,也不规 ...

  4. .net Core 调用EF Core 爬坑

    .net Core 中调用 EF Core项目 首先得建一个类库供.net Core 的主项目引用:其次,在.net Core 中做注入:最后,在页面中调用 1.类库项目中的操作 1.新建类库项目 2 ...

  5. Myeclipse WEB工程JSP使用JNDI 数据库连接池连接Mysql数据库

    在网上查了很多,最后实现了.下面写一下过程: 首先,在WEBROOT/META-INF下建一个文件context.xml,内容为: <?xml version="1.0" e ...

  6. springboot druid 数据库连接池连接失败后一直重连

    在使用个人阿里云测试机,在查询实时输出日志时,看到数据库连接失败后,服务器一直在重连服务器.开始以为是遭受重复攻击,后面把服务重启后,就没有出现一直重连的情况.看以下输出日志: 2022-02-09 ...

  7. net core 小坑杂记之配置文件读取 02 (控制器里读)

    上次更新博客的时候提到了如何在EF的上下文里读取配置,这次介绍一下在控制器里如何读取. 先说一种简单易懂的: 首先以键值对的形式在appsettings里添加一条配置信息,接着Startup里注入配置 ...

  8. 使用 EF Core 的 EnableRetryOnFailure 解决短暂的数据库连接失败问题

    阿里云服务器有时会出现短暂的连接不上数据库服务器(RDS)的问题,之前由于没有启用 Entity Framework Core 的失败重试功能(默认是禁用的),短暂的连接失败立马会引发下面的异常从而出 ...

  9. EF Core 小技巧:迁移已经应用到数据库,如何进行迁移回退操作?

    场景描述:项目中存在两个迁移 Teacher 和 TeachingPlan ,TeachingPlan 在 Teacher 之后创建,并且已经执行 dotnet ef database update ...

随机推荐

  1. Node.js使用jszip实现打包zip压缩包

    一.前言 最近有这样的一个需求,需要把两个同名的.mtl文件和.obj文件打包成一个同名的.zip压缩包.刚开始文件不多的时候,只有几个,或者十几个,甚至二三十个的时候,还能勉强接受手动修改,但是随着 ...

  2. P5290 [十二省联考2019]春节十二响

    题目地址:P5290 [十二省联考2019]春节十二响 骗分方法 如果你实在一点思路也没有,暴力都不会打,那么请考虑一下骗分. 方法一 输出所有 \(M\) 的和. 期望得分:0分. 实际还有5分 方 ...

  3. C语言网蓝桥杯1116 IP判断

    判断IP地址的合法性, 1.不能出现除数字和点字符以外的的其他字符 2.数字必须在0-255之间,要注意边界. 题目分析: 因为一个IP是又四个数字组成,且可能存在符号和其他字符,故不能用整型数组处理 ...

  4. POJ 1269 Intersecing Lines (直线相交)

    题目: Description We all know that a pair of distinct points on a plane defines a line and that a pair ...

  5. Python 官方中文教程(简)

    Python 官方教程 前言 这是一次系统学习Python官方教程的学习笔记 整个教程一共16章, 在学习过程中记录自己不知道的和一些重要的知识, 水平有限, 请指正. Python3.7 官方教程. ...

  6. Lua中的语句

    [赋值] 赋值的基本含义是修改一个变量或一个table中字段的值,这个和其它语言没有多少区别,但是对于Lua,有一个特性,它允许“多重赋值”,也就是一下子将多个值赋予多个变量,例如以下代码: , pr ...

  7. 帆软报表(finereport)图表——扇形图/等弧度的玫瑰图

    扇形图/等弧度的玫瑰图,展示的是展示数据所占的比例,需要所有数据的和加起来为1. 下面利用一个实例说明玫瑰图的用法和设置起始角度和终止角度,操作如下: 1.配置一个内置数据集 新增一个等弧度的玫瑰图模 ...

  8. yum install 报错[Errno 14] curl#37 - Couldn't open file /mnt/repodata/repomd.xml

    最近在玩centos7,之前装系统没太注意yum这个东东,今天用别人装好的系统想用yum install 一个东西,结果报各种错,所以就是: 1.然后按照网上的一些修改,先是执行: yum cleam ...

  9. echarts tree 树型图层级距离设置

    网上找了半天,没有找到设置层级距离的属性,默认是自动适应的,无奈只能改源码,分享出来希望可以帮到有相同需求的... 上github下载echarts源码包,打开src=>chart=>tr ...

  10. 【python】随机数用法

    全文拷贝自:Python随机数用法 random.seed(int) 给随机数对象一个种子值,用于产生随机序列. 对于同一个种子值的输入,之后产生的随机数序列也一样. 通常是把时间秒数等变化值作为种子 ...