.Net多线程:SQL ConnectionPool

时间:2020-03-06 14:41:57  来源:igfitidea点击:

目前,在VB.Net Windows服务中,我正在使用以下方式合并工作单元:

ThreadPool.QueueUserWorkItem(operation, nextQueueID)

在每个工作单元(或者为便于理解,我将使用线程)中,它将进行一些MSSQL操作,如下所示:

Using sqlcmd As New SqlCommand("", New SqlConnection(ConnString))
        With sqlcmd
            .CommandType = CommandType.Text
            .CommandText = "UPDATE [some table]"

            .Parameters.Add("@ID", SqlDbType.Int).Value = msgID

            .Connection.Open()
            .ExecuteNonQuery()
            .Connection.Close()   'Found connections not closed quick enough'
        End With
    End Using

当在服务器上运行netstat -a -o时,我看到大约有50个SQL Server连接位于IDLE或者ESTABLISHED上,这对我来说似乎过分,尤其是因为我们拥有更大的Web应用程序5-10个连接。

连接字符串是应用程序的全局字符串(不变),并且还定义了" Pooling = true"。

现在这些线程中的每个线程都有自己的ConnectionPool,还是整个.EXE进程都有一个ConnectionPool

解决方案

从MS Docs-

"连接是按进程,按应用程序域,按连接字符串以及使用集成安全性时,按Windows标识池化的"

http://msdn.microsoft.com/zh-CN/library/8xx3tyca.aspx

我们是否遇到诸如以下的错误?

异常详细信息:System.InvalidOperationException:超时已过期。超时时间
从池中获取连接之前经过的时间。这可能已经发生
因为所有池化连接都在使用中,并且已达到最大池大小。

服务中还有多少工作项正在排队?

如果打开的连接数使我们不满意,请控制连接字符串

注意:MinPoolSize和MaxPoolSize。

代码的一个大问题是,如果ExecuteNonQuery引发异常,则我们不会关闭连接。仅仅放置SqlCommand是不够的,当引发异常时,还需要放置SqlConnection,例如:

Using SqlConnection connection = New SqlConnection(ConnString)
    Using sqlcmd As New SqlCommand("", connection)        
        With sqlcmd            
          ... etc
        End With    
    End Using
End Using

尽管我通常喜欢using语句,但是我发现有时在.NET库中,直到垃圾回收之前,句柄的实际CLOSE才完成。因此,出于对此类事物的守旧和宗教信仰,我在using语句的末尾添加了一个明确的结尾。这是pseduo代码,因为我通常使用Crather然后使用VB.NET进行编码,但这应该可以为我们提供帮助。

Using SqlConnection connection = New SqlConnection(ConnString)

   TRY
      Using sqlcmd As New SqlCommand("", connection)
                  With sqlcmd
                        ... etc
          End With
      End Using
   FINALLY
      connection.Close()

End Using