如何解决“当会话处于单用户模式时客户端驱动程序发送了多个请求”

Jam*_*olt 7 sql-server entity-framework

我正在与一位正在努力阻止以下错误的开发人员合作:

服务器将断开连接,因为客户端驱动程序在会话处于单用户模式时发送了多个请求。当客户端在会话中仍有批处理运行时发送重置连接的请求,或者当会话正在重置连接时客户端发送请求时,会发生此错误。请联系客户端驱动程序供应商。

发生此错误时,典型的结果是会话持有锁,但没有运行 SQL(sys.dm_exec_requestssession_id没有行),并导致阻塞,直到它被终止。阻塞的原因很简单,但如何阻止错误发生却不是。

关于这个问题的一些事实:

  • 客户端正在使用实体框架(是的,我知道...),启用了 MARS(是的,我知道...)
  • SQL Server 版本为 10.00.5844(SQL Server 2008 SP3 CU12)。他们可能不会在没有广泛测试的情况下升级主要版本,但应用更新的 CU 是可行的。
  • 客户端程序显示sys.dm_exec_connections为 .Net SqlClient Data Provider
  • 开放连接似乎肯定有MARS启用,如net_transportsys.dm_exec_connections表演Session
  • 我被告知应用程序的连接字符串已启用异步处理,根据Matt Neerincx线程中评论(我无权访问应用程序服务器来确认这一点):

如果在连接字符串上设置 Async=true ,它应该可以防止出现此问题。如果您正在使用 MARS 并在多个并发线程上使用相同的连接,则可能发生的情况是重置连接的调用可能会稍微延迟并触发此错误。如果您设置 Async=true,我们会在客户端驱动程序中执行额外的锁定以防止这种情况发生。

关于此错误的更多信息很少。这似乎表明客户端的程序sp_reset_connection在批处理仍在运行时正在调用。我可以设置一个跟踪来确认这一点,但我必须记录很多不相关的活动,而且问题每隔几天才会发生一次。此外,我不确定开发人员是否能够利用这些证据来解决问题。

作为 DBA 或系统管理员,我是否可以使用任何其他技术来进一步解决此问题,或者我可以向开发人员提出任何可能为他提供有用信息或使问题不太可能发生的建议?

Sol*_*zky 5

我没有看到任何地方说明正在使用哪个版本的 .NET Framework,但考虑到这个问题是在 2014 年 5 月提出的,并且 .NET Framework 版本 4.5 于 2012 年 8 月 15 日发布,以下内容关于SqlConnection.ConnectionStringAsynchronous Processing/Async关键字的注释似乎相关:

从 .NET Framework 4.5 开始,此属性将被忽略。

因此,找出正在使用的实体框架的确切版本以及 .NET Framework 的目标版本可能会有所帮助。

然而,听起来这个问题可能是连接池的结果。我怀疑连接池,因为在有关连接关闭的错误消息之后,会话仍然存在。

首先要尝试的是通过将以下内容添加到连接字符串来简单地禁用连接池:

Pooling=false;
Run Code Online (Sandbox Code Playgroud)

如果问题再也没有出现,那么这很可能就是问题所在。我犹豫是否要说这问题所在,因为这并不是确切的证据。它可能只是将频率从“每隔几天一次”减少到每隔几周甚至几个月一次。但是,如果这确实改善了情况,但应用程序频繁访问服务器,并且如果可能的话您更愿意使用连接池,那么您可以尝试重新引入连接池,但在有限的意义上:您可以为Connection Lifetime关键词:

Connection Lifetime=2;
Run Code Online (Sandbox Code Playgroud)

如果连接超过 2 秒,则连接将在返回连接池时关闭。这允许执行一系列快速查询,而无需每个查询都花费时间建立连接,同时不允许连接在那里徘徊,可能持有锁定等。

即使错误仍然发生,通过不让连接池保持会话和连接处于活动状态,也应该允许进行适当的清理、释放锁等。


只是为了说明这一点,因为它在问题的评论中受到质疑:实体框架使用多个活动结果集(MARS)来执行延迟加载。因此,如果应用程序已开发为使用延迟加载,则不能选择关闭 MARS。