【问题标题】:SQL Server disconnection causes connection pool issuesSQL Server 断开连接导致连接池问题
【发布时间】:2012-09-25 00:48:27
【问题描述】:

我有一个 Windows 服务,它通过 RabbitMQ 接收消息,这会触发一个事件处理程序,它会做一些工作,然后尝试将结果保存到数据库中。它的线程使用:

ThreadPool.QueueUserWorkItem(ProcessMessageOnThread, messageReceived);

其中ProcessMessageOnThread 是在messageReceived 上执行工作的方法,messageReceived 表示从 RabbitMQ 出列的消息。

正常情况下windows服务按预期运行,即出队、处理、持久化。

我想确保我的所有消息都得到处理并给予公平的更改以进行处理,因此如果我无法打开与 SQL Server 的连接,我只需将消息重新排队以再次处理它(希望那个时候SQL Server 将回来,否则这将继续 - 我对此很好)。

现在问题来了,当进程按预期运行一段时间后,SQL Server 连接池已满,然后 SQL Server 断开连接,现在这是事情发生的时候有点不稳定。

可能会发生以下两种情况之一:

  • connection.Open() 引发异常 - 但是我发现了这个,所以不用担心

  • cmd.ExecuteNonQuery() 引发异常 - 我正在执行存储过程

这是我需要弄清楚如何处理的第二个选项。以前我假设这里的任何异常都意味着我传递给存储过程的数据存在问题,因此应该将其移出队列并让其他东西对其进行分析。

但是,现在我认为我需要一种新方法来处理异常与实际未建立的连接有关的情况。

我查看了SqlException 类,并注意到一个名为Class 的属性,它的描述为Gets the severity level of the error returned from SQL Server,现在关于此的信息显示:

严重级别为 10 或更低的消息是信息性的,表示由于用户输入的信息错误导致的问题。从 11 到 16 的严重级别由用户生成,并且可以由用户进行更正。从 17 到 25 的严重级别表示软件或硬件错误。当发生 17、18 或 19 级错误时,您可以继续工作,尽管您可能无法执行特定语句。

这是否意味着修复我的异常处理我可以只检查if (ex.Class > 16) 然后重新排队消息,因为问题在于连接else 将其丢弃,因为它很可能与发送到存储过程的格式错误的数据有关?

所以问题是,我应该如何进行异常处理以及在调用cmd.ExecuteNonQuery() 时,如果抛出的异常是由于断开的连接而导致的。


更新:

我之前遇到过连接未返回到池中的问题(这是由于线程问题造成的),并且已经解决了这些问题,因此我确信问题与未返回到池中的连接无关水池。此外,围绕连接的用途的逻辑非常简单,我也确保它们始终关闭......所以我对与 Sql Server 断开连接然后捕获行为有关的答案更感兴趣cmd.ExecuteNonQuery()

【问题讨论】:

    标签: c# sql-server design-patterns connection-pooling


    【解决方案1】:

    连接池中的连接可能会由于各种原因进入奇怪的状态,所有这些都与糟糕的应用程序设计有关:

    • 在关联的数据读取器之前关闭连接
    • 更改池不重置的设置(如事务隔离级别)
    • 启动异步查询 (BeginOpenReader),然后在异步处理程序触发之前将连接返回到池

    您应该调查您的应用程序并确保正确地将连接返回到池中。有助于调试的一件事是在开发环境中减小应用程序池的大小。您在连接字符串中更改池的大小:

    ...;Integrated Security=SSPI;Max Pool Size=2;Pooling=True;
    

    这使得池问题很容易重现。

    如果您找不到原因,但仍需要部署修复程序,您可以使用ClearPoolClearAllPools 之一。当您在Open()ExecuteNonQuery() 之后检测到可疑异常之一时,这样做的一个好地方。两者都是SqlConnection 类的静态方法:

    SqlConnection.ClearPool(yourConnection);
    

    或者更粗略的方法:

    SqlConnection.ClearAllPools()
    

    请注意,这基本上是Pokémon Exception Handling。如果它有效,您将不知道为什么。 :)

    【讨论】:

    • 我之前遇到过连接没有返回到池中的问题(这是由于线程问题造成的)并且已经解决了这些问题,所以我相信这个问题与连接无关不会回到游泳池。此外,围绕连接的用途的逻辑非常简单,我也确保它们始终关闭......所以我对与 Sql Server 断开连接然后捕获行为有关的答案更感兴趣的 cmd.ExecuteNonQuery()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    相关资源
    最近更新 更多