这很有意思。我正在尝试删除表中的一堆记录(约200万)。在等待大约4个小时进行简单删除后,我开始调查。
delete from mytable where date > getutcdate()
如果我执行一些计数查询,总行数会增加,但最大ID(标识)不会更改。
select count(1) from mytable with(nolock)
select max(Id) from mytable with(nolock)
我确保通过杀死不是来自我的IP地址的每个会话来打开唯一的连接。
select * from sys.dm_exec_connections
kill 123
kill 124
kill 125
-- etc
然而,总行数增加且最大Id保持不变。到底是什么导致了这个?
更新
看起来我的原始查询仍在运行。我发誓我已经杀了它,但如果我现在试图杀死它,它会说“命令已成功完成”,但如果我再次运行此查询,它仍显示为正在运行:
SELECT *
FROM sys.dm_exec_sessions s
LEFT JOIN sys.dm_exec_connections c
ON s.session_id = c.session_id
LEFT JOIN sys.dm_db_task_space_usage tsu
ON tsu.session_id = s.session_id
LEFT JOIN sys.dm_os_tasks t
ON t.session_id = tsu.session_id
AND t.request_id = tsu.request_id
LEFT JOIN sys.dm_exec_requests r
ON r.session_id = tsu.session_id
AND r.request_id = tsu.request_id
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) TSQL
更新2
行计数最终停止上升,锁被释放,所以看起来它已经回滚了几个小时。在我的老板的帮助下,我刚刚在今晚(美国东部标准时间凌晨2点)上网,我们重建了一些索引并尝试了不同的方法。
DELETE_MORE:
DELETE TOP(5000) from mytable where date > getutcdate()
IF @@ROWCOUNT > 0 GOTO DELETE_MORE
是的,这是一个GOTO。是的,这是我在职业生涯中找到的唯一原因。现在已经不在了......这将删除5000个组中的行,如果失败则最小化锁定和回滚。这似乎运行良好,因为它在我输入时运行。
答案 0 :(得分:1)
如果你完全排除了修改表的其他人,那么很可能回滚仍在完成。使用nolock查询表会绕过锁定,这样您就可以读取正在回滚的数据,并且可能已经开始以最大ID向后回滚。尝试在没有nolock的情况下执行计数查询。打开一个新会话并执行sp_who2和sp_lock以查看您的查询是否被阻止。执行sp_who2也会显示spid是否正在进行回滚。使用statusonly杀死#spid以获取更多信息。