Gra*_*eme 10 sql-server delete sql-server-2008-r2
我们在一个有 18 亿行的数据库上运行了一个删除查询。这次删除将删除 12 亿行。
事后看来,我们会一次将这个查询分解为 100m,但现在它已经运行了 24 小时,并且日志文件的大小为 2Tb,这似乎是日志文件所允许的最大大小。
数据库处于简单恢复模式。
有没有保存这个查询?还是我们只需要重新启动 SQL Server 看看会发生什么?数据库会无法使用吗?我们可以做些什么来尽可能干净地消除它?
Bra*_*adC 14
首先,检查 SQL 错误日志以查看它是否真的达到了日志的最大大小。如果是这样,则查询没有完成的希望,它可能已经处于回滚状态。
即使是这样,我总是更喜欢手动终止 spid(使用sp_who2或sp_WhoIsActive查找 spid,然后执行 akill 59或其他操作)。除非您执行显式 KILL,否则您也无法检查回滚状态,请参阅此相关线程。
由于这是删除,而不是更新或插入,您可能很幸运并发现它立即回滚。如果不是,则回滚可能需要与达到这一点一样长(或更长)的时间。
要查看回滚状态,请使用
kill 59 with statusonly
Run Code Online (Sandbox Code Playgroud)
不幸的是,我发现这经常没有显示任何有用的东西,只是“0% 完成”。在这种情况下,您必须使用sp_who2并观察 IO 和 CPU 以查看它是否仍在执行某些操作。
关于重启,这是一个严重的风险。如果 spid 正在主动回滚(CPU 和 IO 正在更改),那么重新启动 SQL 只会使数据库完全脱机,直到回滚完全完成(小时和小时)。但是,如果 CPU 和 IO没有移动,那么它实际上可能会立即清除它。无论哪种方式,都是一种风险。
最后一个选择,如果事情特别糟糕:如果您在删除开始之前有备份(并且数据库没有其他更新),那么最快的恢复方法可能是简单地删除数据库,重新启动SQL,并从备份中恢复。
如果你不能删除数据库(或者如果你已经重新启动了实例并且 sql 错误日志预测了 24 小时的恢复时间),那么关闭 SQL 服务,从磁盘中删除 MDF 和 LDF 文件,启动 SQL,删除(ghost) 数据库,并从备份中恢复。
显然,如果这是用户未与之交互的后端处理数据库,您只会尝试这样做。
不要重新启动 SQL 服务器。这只会延长您的痛苦,因为将进行恢复,这将回滚或重做任何未完成的事务,包括您的删除。
杀死正在运行删除的会话将导致发生回滚,这也需要很长时间才能完成。
您想查看以下查询以查看操作的状态:
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;
Run Code Online (Sandbox Code Playgroud)
该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
Run Code Online (Sandbox Code Playgroud)
因此,只有当您已经取消删除语句并且它正在回滚,或者您已经重新启动 SQL Server 并且它正在恢复时,您才会看到该列有意义。
如果该blocking_session_id列包含数字,则表示其他会话正在阻止删除操作。如果该会话自启动以来一直在阻止删除操作,则您可以取消该操作而无需进行任何回滚。