多线程与SqlConnection.Close

本文探讨了一个WindowsForm程序在多线程环境下遇到的数据库连接池问题。在特定条件下,未正确关闭的SqlConnection导致了连接池耗尽,进而引发部分线程无法获取数据库连接的错误。文章分析了问题产生的原因,并提供了解决方案。
摘要由CSDN通过智能技术生成

我做的一个Windows Form 程序碰到一个很怪异的多线程情况,最后检查进去竟然是部分代码的数据库链接没有关闭导致的。

我的这个程序是多线程程序,每个线程不间断的从数据库中取得数据,然后对取出的数据进行处理,一直循环到没有需要处理的数据为至。每个线程的循环是上万次的,即,每个线程上万次的数据库链接打开操作。

这个程序碰到怪异的现象是:

在A服务器上,没有任何问题,在B服务器上程序开一个线程没有任何问题,开多个线程则只有一个线程没问题,其他线程都有问题。

对每一个线程都作 try catch 拦截,就会看到出错线程报如下错误:

超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。

System.Data

   在 System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)

   在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)

   在 System.Data.SqlClient.SqlConnection.Open()

从这个异常就可以看到,是数据库链接对象池中没有可用的链接了。

再分析下去,就是其中一部分从数据库中读数据的代码,没有调用 SqlConnection.Close。

 

分析我这个程序出现的规律:

单线程,不主动调用 SqlConnection.Close

这时候竟然数据库链接池不会报没有可用资源:

数据库链接对象池的默认最大容量为100,单线程对数据库链接打开的请求超过10000的。

显然这种情况下,虽然没有手工SqlConnection.Close,但是这些数据库链接SqlConnection还是回到了数据库链接对象池中了。

多线程时,不主动调用 SqlConnection.Close。

只有一个线程在跑,其他线程都报上述错误。

显然,多线程时,数据库链接对象池都被一个线程占住了,其他线程获得不了可用分数据库链接。

 

这个多线程怪异的特征,之前一直没想到会是SqlConnection.Close导致的,一直在其他方面想可能的问题。这次经验教训后,心得就是:

  • try catch 只能拦截当前线程的异常,它拦截不到其他线程的。
  • 多人协作开发,并且程序经过多次修改bug后,完全有可能出现某些情况下,没有关闭数据库链接的情况,这种情况如何避免,是必须深思的一个问题。
  • 单线程,不主动关闭SqlConnection,有可能仍然不报错误,但是多线程下,就可能报错误了。

 

参考资料:

FIX: Error message when a "System.Data" thread tries to open a pooled connection in the .NET Framework 2.0: "Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool
http://support.microsoft.com/kb/948868

http://support.microsoft.com/kb/948868/en-us

 

使用连接池
http://msdn.microsoft.com/zh-cn/library/8xx3tyca(VS.80).aspx

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值