我们在具有18亿行的数据库上运行了删除查询。此删除操作将删除12亿行。
事后看来,我们会一次将这个查询分解为100m,但是我们处于一个已运行24小时且日志文件位于2Tb的位置,这似乎是日志文件允许的最大大小。
数据库处于SIMPLE恢复模式。
是否有保存此查询的内容?还是只需要重启SQL Server看看会发生什么?数据库将无法使用吗?我们有什么办法可以尽可能彻底地消除这种情况?
我们在具有18亿行的数据库上运行了删除查询。此删除操作将删除12亿行。
事后看来,我们会一次将这个查询分解为100m,但是我们处于一个已运行24小时且日志文件位于2Tb的位置,这似乎是日志文件允许的最大大小。
数据库处于SIMPLE恢复模式。
是否有保存此查询的内容?还是只需要重启SQL Server看看会发生什么?数据库将无法使用吗?我们有什么办法可以尽可能彻底地消除这种情况?
Answers:
首先,检查SQL错误日志以查看它是否真的达到了日志的最大大小。如果这样做了,那么查询就没有希望完成的希望,它可能已经处于回滚状态。
即使是这样,我也总是喜欢手动杀死spid(使用sp_who2
或sp_WhoIsActive
查找spid,然后执行a kill 59
或其他操作)。除非您执行显式KILL,否则您也无法检查回滚状态,请参见此相关线程。
由于这是删除操作,而不是更新或插入操作,因此您可能很幸运,发现它会立即回滚。如果不是这样,回滚可能要花费与之前相同的时间(或更长)。
要查看回滚状态,请使用
kill 59 with statusonly
不幸的是,我发现这经常没有显示出任何有用的东西,仅仅是“ 0%完成”。在这种情况下,您将不得不使用sp_who2
并观察IO和CPU,以查看其是否仍在继续工作。
关于重启,这是一个严重的风险。如果spid正在主动回滚(CPU和IO正在更改),则重新启动SQL将仅使数据库完全脱机,直到回滚完全完成(小时和小时)。但是,如果CPU和IO 没有移动,那么实际上可能会立即清除它。无论哪种方式,都是有风险的。
最后一种选择是,如果情况特别糟糕:如果您在删除操作开始之前就进行了备份(并且没有对数据库进行其他更新),那么恢复的最快方法可能就是简单地删除数据库,然后重新启动SQL,并从备份还原。
如果无法删除数据库(或者如果您已经重新启动实例,并且sql错误日志预计将恢复24小时),请关闭SQL服务,从磁盘上删除MDF和LDF文件,启动SQL,然后删除(ghost)数据库,然后从备份还原。
显然,只有在这是用户未与之交互的后端处理数据库时,您才尝试这样做。
不要重新启动SQL Server。这将只会延长您的痛苦,因为将进行恢复,这将回滚或重做所有未完成的事务,包括删除。
终止正在运行删除操作的会话将导致发生回滚,这也需要很长时间才能完成。
您想查看以下查询以查看操作状态:
SELECT des.session_id
, des.host_name
, des.login_name
, der.command
, der.estimated_completion_time
, der.blocking_session_id
, der.last_wait_type
, der.percent_complete
, der.start_time
, der.status
, der.wait_resource
, der.wait_type
, der.wait_time
FROM sys.dm_exec_sessions des
INNER JOIN sys.dm_exec_requests der ON des.session_id = der.session_id
WHERE des.session_id <> @@SPID
AND des.is_user_process = 1
ORDER BY des.session_id;
仅针对以下操作填充该percent_complete
列以及依赖于该列的列estimated_completion_time
:
ALTER INDEX REORGANIZE
AUTO_SHRINK option with ALTER DATABASE
BACKUP DATABASE
DBCC CHECKDB
DBCC CHECKFILEGROUP
DBCC CHECKTABLE
DBCC INDEXDEFRAG
DBCC SHRINKDATABASE
DBCC SHRINKFILE
RECOVERY
RESTORE DATABASE
ROLLBACK
TDE ENCRYPTION
因此,如果您已经取消了delete语句并且正在回滚,或者如果您已经重新启动了SQL Server并且处于恢复状态,则只会看到该列有意义。
如果该blocking_session_id
列包含数字,则表明其他会话正在阻止删除操作。如果该会话自启动以来一直在阻止删除操作,则您可以取消该操作而无需任何回滚。