最近我们有一个插入数据库的 SQL 作业。该查询已不必要地运行了几天,因此使用 KILL SPID 将其杀死。然后这个过程开始回滚了几天,似乎就挂在那里了。
运行 KILL SPID WITH STATUSONLY 会给出一条消息,指出“预计完成”为 100%,“预计剩余时间”为 0 秒。
最终我们不得不重新启动删除进程的 SQL 服务。
我的问题是——你应该如何杀死一个 SQL 进程?这是唯一的方法吗?
最近我们有一个插入数据库的 SQL 作业。该查询已不必要地运行了几天,因此使用 KILL SPID 将其杀死。然后这个过程开始回滚了几天,似乎就挂在那里了。
运行 KILL SPID WITH STATUSONLY 会给出一条消息,指出“预计完成”为 100%,“预计剩余时间”为 0 秒。
最终我们不得不重新启动删除进程的 SQL 服务。
我的问题是——你应该如何杀死一个 SQL 进程?这是唯一的方法吗?
你做的一切都是正确的,但你已经考虑了回滚的成本。您说您的查询运行了好几天,所以它会将几天的数据作为未提交的事务写入日志文件。通过终止任务,您启动了回滚,这是您必须等待的。
如果您希望能够以较小的影响终止事务,请考虑对事务进行批处理并偶尔进行提交。如果您可以完全避免事务,那么对于长时间运行的作业会更好。
正如您所描述的,我已经看到了回滚“挂起”,摆脱它的唯一方法是像您一样重新启动 SQL 服务。
但重要的是要确保回滚确实挂起,而不是实际上仍然回滚(如您所见, WITH STATUSONLY 并不完全可靠)。风险在于,如果在回滚过程中,你重新启动 SQL 服务,那么在你重新启动 SQL 服务后,数据库将一直处于“恢复”模式,直到回滚完成。
我能说的唯一其他方法是使用刷新 SQL 活动监视器,并查看 SPID 的 CPU 和/或 IO 计数是否仍在增加。如果是,则回滚仍在进行中,您不应该重新启动 SQL。给它更多的时间。
另外一点:不要试图做一些疯狂的事情,比如删除日志文件。这将“停止”事务回滚,但会以数据库的完整性为代价。我使用的唯一其他技术(假设回滚事务是自上次备份以来对数据库的唯一重要更改)是简单地从最新备份恢复,我们确定这比多等一天更快更容易发生回滚。当然,这在很大程度上取决于您的数据库活动的性质。