在目标DB的短强制单用户模式之后,.NET连接池无法恢复

时间:2014-06-26 06:24:50

标签: c# sql-server connection-pooling

我们的应用使用以下连接字符串连接到我们的数据库:

Data Source=<IP>;Initial Catalog=<DBName>;User ID=<Account>;Password=<Password>

它使用它来尝试将数据存储在一个循环中,该循环可以通过遵循伪代码来简化:

bool stored;
do
{
    (using)(SqlConnection conn = new SqlConnection(StaticConnectionString))
    {
        try
        {
            conn.Open();
            //Create SP command and execute here
            stored = true;
        }
        catch(Exception e){/* Log and sleep few secs */}
    }

}while(!stored)

由于设计错误,我们遇到了阻塞和极高磁盘I / O的问题。我们将DB置于单用户模式:

ALTER DATABASE <DBName> SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

修复了问题,然后将数据库翻转为MULTI_USER。 之后我们的exe的所有其他实例都重新连接到数据库 - 但是试图插入大量数据的exe(前一个循环在几十个并行线程中运行以用于不同的记录)在此之后的一小时内没有恢复(比我们重新启动)。在尝试连接时,它一直在跟踪异常:

System.Data.SqlClient.SqlException (0x80131904): Cannot open database "<DBName>" requested by the login. The login failed.
Login failed for user '<Account>'.
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.Open()
   at <Our Call to Connection.Open>
ClientConnectionId:9dcf1a45-0f53-4a0f-be8b-63d871ca0afd

所有线程都在为同一个内部连接遇到问题(.NET framweork连接池ClientConnectionId guid在此问题的所有堆栈跟踪中重复)。在TCPView和进程监视器中,我可以清楚地看到应用程序甚至没有尝试创建与服务器的新连接 - 它只是在某种程度上内部记住由于SINGLE_USER模式连接失败并在下次尝试时重新抛出异常,并且池没有尝试清除这样的连接。 我试图强制几个完整的GC - 没有变化,分离附加数据库 - 没有变化;禁止网络访问sql server并重新启用它 - 没有变化。

为什么连接池没有丢失连接失败?我们如何解决这个问题?

0 个答案:

没有答案