现象
大家知道,在.Net/.Net Core下,我们使用的MySql.Data库,它默认开启开启连接池模式的,同时也有最小连接池和最大连接池的配置:
连接字符串参数 | 说明 | 默认值 |
---|---|---|
Pooling | 是否启用连接池 | true |
MinPoolSize | 最小的连接池数 | 0 |
MaxPoolSize | 最小的连接池数 | 100 |
如果请求高峰期的时候, 连接一般就不够用,只要没满足MaxPoolSize,就会一直创建连接。
可是到了低峰期后,通过show processlist查看mysql的连接情况,发现并没释放和回收,而且每个Sleep的连接了几秒后又被使用了,这是为什么呢?
原因
这就要来看MySql.Data的连接池管理源码了,定义了两个池, 一个是正在使用池_inUsePool(List),另一个是空闲池_idlePool(Queue),连接使用完后会放回空闲池_idlePool。
1 2 3 4 5 6 7 8 9 10 11 |
namespace MySql.Data.MySqlClient {<!-- --> internal sealed class MySqlPool {<!-- --> private readonly List<Driver> _inUsePool; private readonly Queue<Driver> _idlePool; ...... |
那对空闲队列的回收机制是如何的呢?看到内部定义了一个Timer的定时任务,写死了对空闲超过180秒的连接,从空闲池_idlePool去除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
internal static int maxConnectionIdleTime = 180; .... .... .... private static Timer timer = new Timer(CleanIdleConnections, null, (maxConnectionIdleTime * 1000) + 8000, maxConnectionIdleTime * 1000); .... .... .... 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(永久) |
这个缺点是,无论连接是否空闲,都会在时间达到后关闭。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。