我们从客户端获得票证,该票证有时会从查询中获取部分数据。简单的单词查询是视图查询:
SELECT column1, column2, column3, column4, column5, column6 ... column50
from [dbo].[view]
查看返回大约 300 万条记录。在服务器上,我们有一些规则会在运行 30 分钟后终止查询。在正常情况下,此查询运行大约 5 分钟,但在工作量大的情况下,此查询运行超过 30 分钟。在这种情况下,客户端可能会遇到两种错误:
• 返回的终止查询
“消息 596,级别 21 无法继续执行,因为会话处于终止状态”
这会导致应用程序导入节点失败,因此是“理想”情况,因为它们不依赖于具有部分输入数据集的工作流。
• 一个与杀死进程相关的场景
“消息 0,级别 20 当前命令发生严重错误”
从 ODBC 的角度来看,这看起来与成功运行相同,因此我们以部分数据集结束 - 这是最危险的情况。
你知道如何避免这种问题吗?
您遗漏了第二个错误中最重要的部分(强调我的):
无论“应用程序导入节点”是什么,它都需要通过丢弃结果集来处理此错误 - 并可能撤消它对迄今为止已流式传输的结果所做的任何工作。
任何其他解决方案都将是一种解决方法,并且可能是不安全的解决方案。
重要的是要注意,虽然
KILL
spid 会导致此错误,但从磁盘读取损坏的页面也是如此。如果您意外看到此错误,您应该运行DBCC CHECKDB
以确保您的数据是安全的。我用 C# 编写了一个小程序,它创建一个 ODBC 连接(使用
System.Data.OdbcConnection
该类)并从一个长时间运行的查询中开始流式传输结果:每次我运行程序时,我都会等待几秒钟,然后
KILL
在运行我的查询的 spid 上发出一个命令。我在我的计算机上使用四种不同的 ODBC 驱动程序进行了尝试,但都遇到了错误:
我得到的错误如下:
用于 SQL Server 的 ODBC 驱动程序 17
SQL 服务器
SQL Server 本地客户端 11.0
SQL Server 本机客户端 RDA 11.0
和以前一样
综上所述,应用程序应该在被终止的连接上出现错误。它应该具有处理查询被终止时结果可能尚未完成的事实的逻辑。
我们有一个类似的问题,除了我们的初始查询被网络中断杀死。这反过来又破坏了我们正忙于重建的索引之一。结果?我们终于发现,如果你查询某个表,SQL 就会进入 kill 状态。我手动重建了每个索引,然后在每次重建后测试了表。终于找到了导致问题的索引,我删除了它,重新创建了它,一切从那里顺利进行。
SQL 日志、事件查看器条目、SSRS 日志在这方面几乎毫无用处……