在您描述的情况下,确实没有办法防止数据丢失。SQL Server 旨在检测死锁并自动选择要杀死的受害者(当然,除非您使用DEADLOCK_PRIORITY
指定哪个查询不太重要)。这意味着必须进行回滚,并且 SQL Server 必须进行内务处理以确保数据一致性。你在干涉那个。丢失数据根本没有办法。
假设您有两个查询试图使用一个资源并且出现了死锁。一段时间后,SQL Server 检测到这一点并决定终止一个线程。因为 SQL Server 遵循ACID的原则,所以查询不仅会自动停止,还会开始回滚。如果此查询进行了大量更改,则意味着 SQL Server 必须滚动浏览日志并撤消所有更改,然后才能停止线程。这意味着在 SQL Server 发现死锁和解决死锁之间可能会经过非常非常长的时间。在任何时候,您都不应尝试通过杀死死锁 SPID 来加快进程。
这更多是组织和操作上的限制,而不是技术限制。您和使用 SQL Server 的员工必须知道,如果您开始查询,它必须完成。这意味着查询是否完成,遇到错误并且必须回滚,选择在死锁场景中被杀死并且必须回滚等等,所有查询都必须完成。知道这一点后,您应该以无法杀死 SPID 的心态向前迈进,因为它们需要很长时间或因为它们陷入僵局。如果您因为生产力损失而被利益相关者追捕以杀死 SPID,请告知他们为什么有问题的查询必须运行到完成以及如果您进行干预可能会发生什么(生产数据丢失)。谈论业务风险,而不是“我们应该”或“我们不应该”。如果利益相关者不相信并且仍然希望您执行诸如杀死 SPID 之类的操作,请升级到您的管理层并让他们做出决定。如果您是管理层,请非常清楚地记录利益相关者要求您做一些危险的事情并准备好该文档。相信我,他们会问为什么生产服务器整天都在停机,您需要能够清楚地记录所有玩家及其角色。
此外,教育使用服务器的员工将大事务分解为较小的事务,或使用BEGIN
/ COMMIT
。这样,如果出现问题并且必须回滚查询,则需要几分钟或几小时而不是几天。在过去的 2 年里,我们办公室的数据呈爆炸式增长,现在我们有几张表,每张表的行数都超过了 10 亿行。学习期间非常痛苦:我们有很多周的时间都在效率低下,因为人们试图进行大量更新或构建非常大的数据集,出现错误,随后的回滚持续了 DAYS 天。在我们学习并实施了一些标准操作程序以将查询分解为更小的批次之后,情况变得更好了。尽管如此,如果 DBA 刚刚开始杀死 SPID 会发生什么,我还是不寒而栗。
总而言之,如果您继续杀死 SPID,您将无法防止数据丢失。您必须让 SQL Server 继续管理查询,直到它完成或终止并完成回滚。如果您尝试手动终止这些查询,您将丢失数据。没有办法解决这个问题。
进一步阅读:
http://msdn.microsoft.com/en-us/library/aa480356.aspx
http://technet.microsoft.com/en-us/library/aa213030%28v=sql.80%29.aspx
https://www.simple-talk.com/sql/database-administration/handling-deadlocks-in-sql-server/