在很多情況下,往往會要求數(shù)據(jù)庫管理員終止SQL Server中的用戶進程,例如在停止某個數(shù)據(jù)庫的運作時,或者還原數(shù)據(jù)庫之前,或者長時間運行活動事務(wù)等情況下。數(shù)據(jù)庫管理員通常會使用SQL Server中提供的“KILL”命令來完成任務(wù)。
但是,SQL Server提供的“KILL”命令靈活性不夠,不能在一次性結(jié)束多個會話,一次只能解決掉一個會話。本文將為大家介紹如何創(chuàng)建一個簡單的存儲過程來實現(xiàn)同時終止多個會話、結(jié)束連續(xù)的會話和結(jié)束連接到數(shù)據(jù)庫的所有會話等功能。
首先,我們在主數(shù)據(jù)庫中創(chuàng)建“KILL2”這個進程,代碼如下所示(參考圖一)
USE [master] |
begin
print 'Killing '+convert(varchar(100),@startcount)
set @killcmd ='Kill '+convert(varchar(100),@startcount)
exec(@killcmd)
end
else
begin
Print 'Cannot kill the SPID ' +convert(varchar(100),@startcount) + ' because it does not Exist'
end
set @startcount=@startcount + 1
end
end
if CHARINDEX(',',@param) <> 0
begin
set @tempvar =@param
while charindex(',',@tempvar ) <> 0
begin
SET @tempvar2=left(@tempvar,charindex(',',@tempvar)-1)
set @spid=(select spid from master.dbo.sysprocesses where spid=CONVERT(varchar(100),@tempvar2) and spid>50)
if @spid = CONVERT(varchar(100),@tempvar2)
begin
print 'Killing '+CONVERT(varchar(100),@tempvar2)
set @killcmd='Kill '+CONVERT(varchar(100),@tempvar2)
exec (@killcmd)
end
else
begin
Print 'Cannot kill the SPID ' +CONVERT(varchar(100),@tempvar2) + ' because it does not Exist'
end
set @tempvar =REPLACE(@tempvar,left(@tempvar,charindex(',',@tempvar)),'')
end
set @spid=(select spid from master.dbo.sysprocesses where spid=CONVERT(varchar(100),@tempvar) and spid>50)
if @spid = CONVERT(varchar(100),@tempvar)
begin
print 'Killing '+CONVERT(varchar(100),@tempvar)
set @killcmd='Kill '+CONVERT(varchar(100),@tempvar)
exec (@killcmd)
end
else
begin
Print 'Cannot kill the SPID ' +CONVERT(varchar(100),@tempvar) + ' because it does not Exist'
end
end
if CHARINDEX('=',@param2) <>0
begin
print 'Killing all the SPIDs that are connected to the database '+RIGHT(@param2,(len(@param2)-3))
declare dbcursor
cursor forward_only for select SPID from master.dbo.sysprocesses where DB_NAME(dbid) = RIGHT(@param2,(len(@param2)-3))
open dbcursor
fetch dbcursor into @spid
while @@FETCH_STATUS =0
begin
set @spid2=(select spid from master.dbo.sysprocesses where spid=@spid and spid>50)
if @spid = @spid2 begin
print 'Killing '+CONVERT(varchar(100),@spid2)
set @killcmd='Kill '+CONVERT(varchar(100),@spid2)
exec (@killcmd)
end
else begin Print 'Cannot kill the SPID ' +CONVERT(varchar(100),@spid2) + ' because it does not Exist' end fetch dbcursor into @spid end close dbcursor deallocate dbcursor end if CHARINDEX('-',@param)=0 and CHARINDEX(',',@param) = 0 and CHARINDEX('=',@param)=0 begin set @spid=(select spid from master.dbo.sysprocesses where spid=CONVERT(varchar(100),@param) and spid>50) if @spid = CONVERT(varchar(100),@param) begin print 'Killing '+CONVERT(varchar(100),@param) set @killcmd='Kill '+CONVERT(varchar(100),@param) exec (@killcmd) end else begin Print 'Cannot kill the SPID ' +CONVERT(varchar(100),@param) + ' because it does not Exist' end end go --kill2 '51' --go --kill2 '51-56' --go --kill2 '56,57,58,52' --go --kill2 'db=AdventureWorks2008' --kill2 'db=My Database' --go --sp_who |
圖一
用法一
現(xiàn)在,我們假設(shè)進程ID(SPID)為51、52、53、54、55、57這幾個進程(見圖二)連接到了SQL Server數(shù)據(jù)庫,而我們只想把進程ID為54、55和57的進程結(jié)束掉。
圖二
執(zhí)行以下命令。注意,在這個例子當(dāng)中還在命令中加入了其他幾個SQL Server中不存在的SPID:61和100。
use master go kill2 '54,57,55,61,100' go |
運行結(jié)果:
Killing 54 Killing 57 Msg 6104, Level 16, State 1, Line 1 Cannot use KILL to kill your own process. Cannot kill the SPID 55 because it does not Exist Cannot kill the SPID 61 because it does not Exist Cannot kill the SPID 100 because it does not Exist |
圖三
我們可以從結(jié)果(見圖三)看到,執(zhí)行指令后成功終止了SPID 54。當(dāng)試圖終止57時失敗了。同時結(jié)果也顯示了為什么沒能終止特定SPID的信息。
用法二
下面,假設(shè)我們有51、52、53、54、55、57、58、59和60這幾個SPID,而我們的目標是結(jié)束SPID從25到70的進程。
執(zhí)行以下命令:
use master go kill2 '25-75' go |
運行結(jié)果:
Killing all SPIDs from 25 to 75 Cannot kill the SPID 25 because it does not Exist ….. Cannot kill the SPID 48 because it does not Exist Cannot kill the SPID 49 because it does not Exist Cannot kill the SPID 50 because it does not Exist Killing 51 Killing 52 Killing 53 Killing 54 Killing 55 Cannot kill the SPID 56 because it does not Exist Killing 57 Msg 6104, Level 16, State 1, Line 1 Cannot use KILL to kill your own process. Killing 58 Killing 59 Killing 60 Cannot kill the SPID 61 because it does not Exist ..... Cannot kill the SPID 75 because it does not Exist |
圖四
從結(jié)果(見圖四)我們可以看到“KILL2”存儲過程忽略了所有SPID小于50的連接,而結(jié)束了從51到70的所有進程。
用法三
接下來,假設(shè)我們要終結(jié)掉所有連接到數(shù)據(jù)庫AdventureWorks2008的會話,同時又假設(shè)SPID為53、54、58和60的進程連接到了該數(shù)據(jù)庫(見圖五)。
圖五
現(xiàn)在,我們執(zhí)行以下的T-SQL語句結(jié)束掉所有這些會話。
Use master go kill2 'db=AdventureWorks2008' go |
運行結(jié)果:
Killing all the SPIDs that are connected to the database AdventureWorks2008 Killing 53 Killing 54 Killing 58 Killing 60 |
圖六
從結(jié)果(見圖六)我們可以看到“KILL2”存儲過程終止了所有連接到AdventureWorks2008數(shù)據(jù)庫的會話。
用法四
“KILL2”存儲過程的第四種用法類似于“KILL命令,也就是一次解決一個會話,如下所示:
Use master go kill2 '56' go |