我有四个连续运行的 SQL 代理作业。每个作业都在执行一个存储过程,该过程查询最近的 ATM 交易,所有这些都通过同一个链接服务器进行。这发生在每个作业的循环中,在 proc 执行之间有 5 秒的延迟(使用 WAITFOR DELAY)。
具体来说,四个作业之一使用一个存储过程,而其他三个作业都使用另一个。每个作业执行都有自己的一组参数,这些参数与将触发响应的特定事务模式相关。他们都在查询同一个链接服务器。
大多数时候,一切正常。但偶尔(几乎*)任何作业都会因以下错误而失败:
TCP 提供程序:指定的网络名称不再可用。[SQLSTATE 42000](错误 64)链接服务器“ATMDB”的 OLE DB 提供程序“SQLNCLI11”返回消息“通信链接失败”。[SQLSTATE 01000](错误 7412)。
这仅在作业更新为使用 WAITFOR 循环连续运行之后才开始发生,而不是作为单独的 SQL 代理作业执行每分钟运行一次。进行此更改是为了避免过多的 SQL 作业日志记录,以及更接近实时地监控 ATM 交易。
他们失败的频率没有一致性,但每天至少有几次。
*我在上面说“几乎”,因为其中一项工作从未失败过。这是最常被“命中”的一个,当发生这种情况时,作业步骤被允许完成,因此我们在 SQL 作业日志中有明确的记录。(然后在 1 秒延迟后再次循环回到第一步。)
所有作业都配置为每分钟运行一次。因此,失败后作业将在下一分钟重新启动,因此这不会对事情造成太大影响。这真是太烦人了!
我怀疑 SQL Native Client 及其实现连接池的方式是问题的根源。在测试时,我将两个过程之一中的链接服务器更新为与另一个不同。两个不同的主机名,但实际上仍然是同一台服务器(我只是使用主机文件创建了一个新名称)。这导致一个作业不再失败,但其他三个作业中的两个仍然会间歇性地失败。在将另一个程序切换为也再次使用相同的链接服务器后,现在所有作业再次偶尔会失败。因为连接池特定于连接字符串,所以不同的服务器名称会导致使用不同的池。
使用 Windows 资源监视器,我可以看到通常有三个 TCP 连接打开到链接服务器。它们在同一个端口上保持打开状态超过几分钟,所以我猜它正在使用某种连接池。当错误发生时,它与关闭的连接之一同时发生,并且在新连接打开后不久。
我目前的理论:因为进程在使用链接服务器时重复循环,连接池的某些问题导致它试图使用因任何原因而关闭的连接。也许每隔一段时间“完成”的一个工作步骤会以某种方式得到刷新,并防止错误发生在该特定过程中。
我尝试将存储过程调用包装在 sp_executesql 中作为“强制”另一个进程或执行上下文的解决方法,但这没有帮助。
两台服务器都是 Windows 2012,运行在 VMWare 中。
关于如何进一步排除故障的任何想法?
将 VM 主机替换为较新的硬件后,问题已自行解决。这表明这是一个网络/硬件级别的问题,而不是由于特定的查询编程方式或 SQL 配置方式造成的。