四天前,一个用户在一个有 400,000,000 行的表上运行了下面的命令。它仍在运行,并且日志文件的大小正在增加。
delete from [table-name]
该表确实有一个未启用检查的外键约束,我知道另一个表中不存在任何行。
数据库在启用“Is Read Committed Snapshot On”的情况下运行并处于简单恢复模式。
在这运行了几个小时后,我发出了一个 kill session 命令,因为我们的日志文件的磁盘空间不足。我添加了另一个日志文件以允许系统继续运行。
日志文件继续增长,当我使用 statusonly 运行 kill session 时,它返回此消息:
SPID 123: transaction rollback in progress. Estimated rollback completion: 0%. Estimated time remaining: 0 seconds.
我不知道如何处理这个查询以使其回滚,也只是了解发生了什么,有人能建议我看什么吗?
DELETE FROM [Some400MRowTable]
太贵了。您删除的每一行都会被记录下来。而当你终止会话时,巨大的事务必须回滚,这更加昂贵。所以通常你只是等待,最终它会回滚。您的替代方法是从备份中恢复。
请注意,这是在 Azure SQL 数据库和 SQL Server 2019 中添加加速数据库恢复的原因之一,它提供“即时事务回滚”,其中回滚成本不是事务所做更改数量的函数。
回滚是单线程的,所以需要更长的时间,虽然 4 天看起来很长,但我们不知道原始删除需要多长时间。来自 Jes Schultz Borland(链接):
根据 BradC 的回答,如果您重新启动 SQL Server,它将在读取事务日志时继续回滚。根据您的备份/恢复计划,从备份中恢复可能是您的最佳选择。
所以删除在你杀死它之前只运行了“几个小时”,而现在“回滚”已经运行了 4 天?
这远远超过了我通常期望的时间,所以我建议:
如果重新启动修复它,你很好。如果没有,那么您的情况不会更糟,那么只需从备份中进行恢复即可。
祝你好运。
您是否考虑过使用 TRUNCATE TABLE 而不是 DELETE?如果您尝试删除具有那么多行的表中的所有行,则 TRUNCATE TABLE 可能是更好的选择。它运行得比 DELETE 快。但是,我也明白,如果你使用它,如果需要,你可能无法回滚。如果我在使用 TRUNCATE TABLE 时对回滚有错误,其他比我聪明的人可以纠正我。