自动终止某些特定任务的会话

Posted

技术标签:

【中文标题】自动终止某些特定任务的会话【英文标题】:Automatically kill session of some specific task 【发布时间】:2016-05-16 11:23:23 【问题描述】:

在某些报表生成中,我们在 SQL Server 中面临死锁问题,所以我能做的是

select * 
from sys.sysprocesses 
where dbid = db_id() 
  and spid <> @@SPID 
  and blocked <> 0  
  and lastwaittype LIKE 'LCK%'

dbcc inputbuffer (SPID from above query result)

dbcc inputbuffer (blocked from above query result)

如果EventInfo 列包含“mytext”,我想终止该部分

Kill 53  

53 不是 SPID 或在我看到我想终止其连接的特定文本时被阻止

每当死锁创建并且找到特定单词时,我想自动执行此过程以终止这些会话。没有用户间隔或动作。

【问题讨论】:

SQL 将在它认为合适的时候分配它自己的死锁受害者(iirc 它基于查询的估计操作员成本)。为什么你觉得有必要自己做这件事?最好先查看 SQL Server 中的隔离级别以阻止死锁。 发生这种情况时,所有用户都会收到错误消息并且条目无法保存。除非我做上述练习。 (现在有完成时间,这种情况经常发生) 如果你要走极端的自动杀死进程,那么你不妨走极端的开启读取提交快照隔离。 您可以将“SET DEADLOCK_PRIORITY LOW”添加到使用“mytext”运行查询的会话中。这样,如果发生死锁情况,如果与另一个优先级正常(默认)或高的会话发生死锁,该会话将被选为牺牲品 恭喜,检查dbareaction :) 【参考方案1】:

有时我使用这个旧查询来摆脱带有特定描述的会话:

declare @t table (sesid int)

--Here we put all sessionid's with specific description into temp table
insert into @t 
select spid
from sys.sysprocesses 
where dbid = db_id() 
  and spid <> @@SPID 
  and blocked <> 0  
  and lastwaittype LIKE 'LCK%'

DECLARE @n int,
        @i int= 0,
        @s int,
        @kill nvarchar(20)= 'kill ',
        @sql nvarchar (255)

SELECT @n = COUNT(*) FROM @t
--Here we execute `kill` for every sessionid from @t in while loop
WHILE @i < @n
BEGIN 
    SELECT TOP 1 @s = sesid from @t
    SET @sql = @kill + cast(@s as nvarchar(10))

    --select @sql
    EXECUTE sp_executesql @sql

    delete from @t where sesid = @s
    SET @i = @i + 1
END

【讨论】:

我不想杀死所有会话,只有特定事件会话在我的数据库中创建死锁,例如“SUBLEDGER”这个词。如果在 eventinfo 中找到这个词,spid 会被上面的 t-sql 杀死 好吧,看看我的回答中的变化,我把你的查询代替了我的。您在 TEMP 表中查询的所有 spid - 而不是在 while 循环中的动态 sql 查询中被杀死。【参考方案2】:

从上面的答案,我根据我的要求进行更改。

/*drop table #inputbuffer 
 --First Time create Table 

create table #inputbuffer
(eventType varchar(255) ,
parameters int ,
procedureText varchar(255),
spid varchar(6))
*/
declare @spid varchar(6)
declare @sql varchar(50)

declare sprocket cursor fast_forward for 
select spid  from SYS.sysprocesses
where dbid =db_id() and spid <> @@SPID and blocked <>0 and lastwaittype LIKE 'LCK%'
union all 
select blocked  from SYS.sysprocesses
where dbid =db_id() and spid <> @@SPID and blocked <>0 and lastwaittype LIKE 'LCK%'

open sprocket
fetch next from sprocket into
@spid

while @@fetch_status = 0
    begin
        set @sql = 'dbcc inputbuffer(' + @spid + ')'
        insert into #inputbuffer(eventType, parameters, procedureText)
        exec (@sql)

        update #inputbuffer
            set spid = @spid
            where spid is null

        fetch next from sprocket into
        @spid
    end

close sprocket
deallocate sprocket

if @@cursor_rows <> 0
    begin 
        close sprocket
        deallocate sprocket
end

DELETE from #inputbuffer  where procedureText NOT like '%SUBLED%'

select spid, eventType, parameters, procedureText from #inputbuffer  

DECLARE @n int,
        @i int= 0,
        @s int,
        @kill nvarchar(20)= 'kill ',
        @sqln nvarchar (255)

SELECT @n = COUNT(*) FROM #inputbuffer

WHILE @i < @n
BEGIN 
    SELECT TOP 1 @s = spid from #inputbuffer 
    SET @sqln = @kill + cast(@s as nvarchar(10))
    select @sqln
    EXECUTE sp_executesql @sqln
    delete from #inputbuffer where spid = @s
    SET @i = @i + 1
END

【讨论】:

【参考方案3】:

这里有更简洁的查询,可以杀死所有运行特定 sql 的会话。

DECLARE @kill varchar(8000); SET @kill = '';
SELECT @kill = @kill + 'kill ' + CONVERT(varchar(5), session_id) + ';'
FROM sys.dm_exec_requests CROSS APPLY sys.dm_exec_sql_text(sql_handle)
WHERE database_id = db_id('dldb') and session_id <> @@SPID 
    and text like '%FROM dl2ResultsHeaderItemSubTree%'
EXEC(@kill);

这从 SQL Server 2005 开始有效。

从List the queries running on SQL Server 和Script to kill all connections to a database (More than RESTRICTED_USER ROLLBACK) 合并。

【讨论】:

以上是关于自动终止某些特定任务的会话的主要内容,如果未能解决你的问题,请参考以下文章

如何解决会话超时问题?

Session

session

Session

Session

关于session