Robin's Blog

记录 积累 学习 成长

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

我做的一个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,有可能仍然不报错误,但是多线程下,就可能报错误了。

 

posted on 2009-08-06 09:30  Robin99  阅读(742)  评论(0编辑  收藏  举报