栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

.Net下MySql空闲连接无法回收释放的原因

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

.Net下MySql空闲连接无法回收释放的原因

现象

大家知道,在.Net/.Net Core下,我们使用的MySql.Data库,它默认开启开启连接池模式的,同时也有最小连接池和最大连接池的配置:

连接字符串参数说明默认值
Pooling是否启用连接池true
MinPoolSize最小的连接池数0
MaxPoolSize最小的连接池数100

如果请求高峰期的时候, 连接一般就不够用,只要没满足MaxPoolSize,就会一直创建连接。
可是到了低峰期后,通过show processlist查看mysql的连接情况,发现并没释放和回收,而且每个Sleep的连接了几秒后又被使用了,这是为什么呢?

原因

这就要来看MySql.Data的连接池管理源码了,定义了两个池, 一个是正在使用池_inUsePool(List),另一个是空闲池_idlePool(Queue),连接使用完后会放回空闲池_idlePool。

namespace MySql.Data.MySqlClient
{
  /// 
  /// Summary description for MySqlPool.
  /// 
  internal sealed class MySqlPool
  {
    private readonly List _inUsePool;
    private readonly Queue _idlePool;
	......

那对空闲队列的回收机制是如何的呢?看到内部定义了一个Timer的定时任务,写死了对空闲超过180秒的连接,从空闲池_idlePool去除。

	// Timeout in seconds, after which an unused (idle) connection 
    // should be closed.
    internal static int maxConnectionIdleTime = 180;
	....
	....
	....
    // we add a small amount to the due time to let the cleanup detect
    //expired connections in the first cleanup.
    //一个定时任务
    private static Timer timer = new Timer(CleanIdleConnections,
      null, (maxConnectionIdleTime * 1000) + 8000, maxConnectionIdleTime * 1000);
	....
	....
	....
	//定时任务会去除空闲180秒的连接
	DateTime expirationTime = d.IdleSince.Add(new TimeSpan(0, 0, MySqlPoolManager.maxConnectionIdleTime));
    if (expirationTime.CompareTo(now) < 0)
	{
	    oldDrivers.Add(d);
        _idlePool.Dequeue();
	}

可是刚好空闲池_idlePool用的是Queue集合, 这个集合是先进先出的集合,也就是说,会优先使用空闲时间最长的连接, 这就导致了一个连接很难达到超过180秒的空闲,所以也就没办法触发回收和释放。

解决方案

暂时没有很好的解决办法,其他小伙伴有方案也可以告知下。
如果允许重新连接MySql耗时不敏感的,可以使用另一个参数:

连接字符串参数说明默认值
ConnectionLifeTime连接池里每个连接的生存时间(以秒为单位)。0(永久)

这个缺点是,无论连接是否空闲,都会在时间达到后关闭。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/955555.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号