【问题标题】:Losing data after killing an SQL spid杀死 SQL spid 后丢失数据
【发布时间】:2014-08-16 09:01:15
【问题描述】:

对于我这个新手 DBA 来说,情况真的很危险。

有时当我看到活动监视器屏幕中出现死锁时,如果查询没有结束并保持挂起状态并且还有一个头块,我必须杀死那个 spid。并非总是如此,但有时,虽然很少,在杀死 spid 后,大量数据从数据库中丢失。 我猜它从锁定开始到我杀死它都会丢失数据。 据我了解,Sql server 不会立即保存数据,它会等待一段时间(某种周期可能每 15 分钟一次)并在认为一切正常时保存数据。

例如,我每 6 小时进行一次完整备份,每 10 分钟进行一次事务备份。昨晚由于某种原因它无法在 00:00 进行备份,并且该 spid 处于挂起状态等待。当我在早上 08:30 杀死那个 spid 时,我从 00:00 到 08:30 丢失了所有表中的所有数据..

我有完整的恢复模式并使用 MsSqlServer2012。

在生产数据库中丢失数据是非常大的风险。 我的问题是;我怎么能确定,SQL 在杀死 spid 之前真的保存了数据吗?

【问题讨论】:

  • 也许您应该解决实际问题,而不是症状...。此外,系统会自动检测死锁并选择受害者进行终止。为什么您甚至需要手动执行此操作?
  • 因为在我杀死锁定的 spid 之前,有些表无法读取。
  • 您必须回滚未提交的事务。没有 15 分钟的保存周期。一旦事务提交,更改必须持续存在。如果您在此之前终止事务,则必须回滚更改。
  • 无论是否有其他 spid 处于挂起状态,您都应该能够进行完整备份(除非这些其他进程也同时尝试进行完整备份)。此外,提交事务时 SQL Server 确保所有更改都已写入磁盘,然后再返回客户端。唯一的例外是如果您在服务器上启用“延迟持久性”,这是 SQL 2014 的新功能,因此不适用于您的 SQL 2012 实例。当你杀死一个 spid 时,你怎么知道你正在丢失数据?
  • 尝试对您的数据库运行 DBCC CHECKDB 以确保它没有损坏。 msdn.microsoft.com/en-us/library/ms176064.aspx 这可能会占用大量资源,因此如果针对生产实例运行,请尝试在非高峰时间运行

标签: sql-server data-integrity spid


【解决方案1】:

在您描述的情况下,确实没有办法防止数据丢失。 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/

【讨论】:

  • 非常感谢您的所有解释和分享您的经验。我将了解 sql 引擎在死锁情况下是如何工作的。那时我杀死了备份 spid,因为它阻塞了系统 8 小时,但现在我明白这是一个错误。
【解决方案2】:

在使用块内的代码中执行我的数据库进程后,所有阻塞问题都消失了。

【讨论】:

    猜你喜欢
    • 2023-03-12
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 2016-06-26
    • 1970-01-01
    • 2013-03-17
    相关资源
    最近更新 更多