数据库问题5-SYS.SYSPROCESSES使用和查找死锁
http://blog.sina.com.cn/s/blog_62c4727d0100jc5z.html
(一)理論部份
包含在 SQL Server 執行個體上執行之處理序的相關資訊。這些處理序可以是用戶端處理序或系統處理序。若要存取 sysprocesses,您必須在 master 資料庫內容中,或者,您必須使用 master.dbo.sysprocesses 三部分名稱。
重要事項: |
---|
此 SQL Server 2000 系統資料表包含回溯相容性的概觀。我們建議您改用目前的 SQL Server 系統檢視表。若要尋找相等的系統檢視或檢視,請參閱<將 SQL Server 2000 系統資料表對應至 SQL Server 2005 系統檢視表>。未來的 Microsoft SQL Server 版本將移除這項功能。請避免在新的開發工作中使用這項功能,並規劃修改目前使用這項功能的應用程式。
|
資料行名稱 | 資料類型 | 描述 |
---|---|---|
spid |
smallint |
SQL Server 工作階段識別碼。 |
kpid |
smallint |
Windows 執行緒識別碼。 |
blocked |
smallint |
封鎖要求之工作階段的識別碼。如果這個資料行是 NULL,表示要求沒有被封鎖,或者封鎖工作階段的工作階段資訊無法使用 (或無法識別)。 -2 = 封鎖資源是由被遺棄的分散式交易所擁有。 -3 = 封鎖資源是由延遲的復原交易所擁有。 -4 = 由於內部閂鎖狀態轉換,而無法判斷封鎖閂鎖擁有者的工作階段識別碼。 |
waittype |
binary(2) |
已保留。 |
waittime |
bigint |
目前的等候時間 (以毫秒為單位)。 0 = 處理序未在等待中。 |
lastwaittype |
nchar(32) |
一個指出上次或目前等待類型之名稱的字串。 |
waitresource |
nchar(256) |
鎖定資源的文字表示法。 |
dbid |
smallint |
處理序目前所使用的資料庫識別碼。 |
uid |
smallint |
執行命令的使用者識別碼。如果使用者和角色數目超過 32,767,則會造成溢位或傳回 NULL。如需詳細資訊,請參閱<查詢 SQL Server 系統目錄>。 |
cpu |
int |
處理序的累計 CPU 時間。不論 SET STATISTICS TIME 選項設為 ON 或 OFF,所有處理序的這個項目都會更新。 |
physical_io |
int |
處理序的累計磁碟讀取和寫入。 |
memusage |
int |
在程序快取中目前配置給此處理序的頁數。負數表示處理序正在釋放其他處理序配置的記憶體。 |
login_time |
datetime |
用戶端處理序登入伺服器的時間。如果是系統處理序,會儲存 SQL Server 起始發生的時間。 |
last_batch |
datetime |
上次用戶端處理序執行遠端預存程序呼叫或 EXECUTE 陳述式的時間。如果是系統處理序,會儲存 SQL Server 起始發生的時間。 |
ecid |
smallint |
用來唯一識別代表單一處理序操作之子執行緒的執行內容識別碼。 |
open_tran |
smallint |
處理序的開啟交易數目。 |
status |
nchar(30) |
處理序識別碼狀態。可能的值為: dormant = SQL Server 正在重設工作階段。 running = 工作階段正在執行一或多個批次。啟用 Multiple Active Result Set (MARS) 之後,工作階段就可以執行多個批次。如需詳細資訊,請參閱<使用 Multiple Active Result Sets (MARS)>。 background = 工作階段正在執行背景工作,例如死結偵測。 rollback = 工作階段正在進行交易回復。 pending = 工作階段正在等候工作者執行緒變成可用狀態。 runnable = 在等候取得時間配量時,工作階段中的工作位於排程器的可執行佇列中。 spinloop = 工作階段中的工作正在等候單一執行緒存取鎖變成可用狀態。 suspended = 工作階段正在等候事件 (例如 I/O) 完成。 |
sid |
binary(86) |
使用者的全域唯一識別碼 (GUID)。 |
hostname |
nchar(128) |
工作站的名稱。 |
program_name |
nchar(128) |
應用程式的名稱。 |
hostprocess |
nchar(10) |
工作站處理序識別碼。 |
cmd |
nchar(16) |
目前正在執行的命令。 |
nt_domain |
nchar(128) |
用戶端的 Windows 網域 (如果使用 Windows 驗證的話) 或信任連接。 |
nt_username |
nchar(128) |
處理序的 Windows 使用者名稱 (如果使用 Windows 驗證的話) 或信任連接。 |
net_address |
nchar(12) |
在每一個使用者的工作站上指派的網路配接器唯一識別碼。當使用者登入時,這個識別碼會插入 net_address 資料行中。 |
net_library |
nchar(12) |
用戶端網路程式庫的儲存資料行。當網路連接時,每個用戶端處理序都會送入。網路連接有與其相關聯的網路程式庫,這可使它們進行連接。如需詳細資訊,請參閱<網路通訊協定和 TDS 端點>。 |
loginame |
nchar(128) |
登入名稱。 |
context_info |
binary(128) |
利用 SET CONTEXT_INFO 陳述式儲存在批次中的資料。 |
sql_handle |
binary(20) |
代表目前正在執行的批次或物件。 注意 這個值是從物件的批次或記憶體位址衍生,而不是使用 SQL Server 雜湊式演算法導出。 |
stmt_start |
int |
開始指定的 sql_handle 之目前 SQL 陳述式的位移。 |
stmt_end |
int |
結束指定之 sql_handle 的目前 SQL 陳述式的位移。 -1 = 目前陳述式執行至指定 sql_handle 之 fn_get_sql 函數傳回的結果尾端。 |
request_id |
int |
要求識別碼。用來識別在特定工作階段中執行的要求。 |
(二)實戰部份
(2.1)恢复数据库而不能获得专门的访问,特别是恢复数据库时候,报错:(数据库正在被其他用户使用)
use master
go
select spid
from sys.sysprocesses
where dbid=db_id('db_Sunrise') and spid<>@@spid
KILL 51;
KILL 52 WITH STATUSONLY;
GO
--返回当前用户进程的会话 ID、登录名和用户名。
SELECT @@SPID AS 'ID',
SYSTEM_USER AS 'Login Name',
USER AS 'User Name'
--如果進程比較多,可以動態執行
declare @sql varchar(8000)
select @sql =coalesce(@sql,'') +'Kill '+CAST(spid AS VARCHAR(10))+ ';'
from sys.sysprocesses WHERE DBID=DB_ID('db_wip')
exec(@sql)
(2.2)查詢死鎖,解決死鎖
概念:
死锁是一种可能发生在任何多线程系统中的状态,而不仅仅发生在关系数据库管理系统中。多线程系统中的一个线程可能获取一个或多个资源(如锁)。如果正获取的资源当前为另一线程所拥有,则第一个线程可能必须等待拥有线程释放目标资源。这时就说等待线程在那个特定资源上与拥有线程有相关性。
如果拥有线程需要获取另外一个资源,而该资源当前为等待线程所拥有,则这种情形将成为死锁:在事务提交或回滚之前两个线程都不能释放资源,而且它们因为正等待对方拥有的资源而不能提交或回滚事务。例如,运行事务 1 的线程 T1 具有 Supplier 表上的排它锁。运行事务 2 的线程 T2 具有 Part 表上的排它锁,并且之后需要 Supplier 表上的锁。事务 2 无法获得这一锁,因为事务 1 已拥有它。事务 2 被阻塞,等待事务 1。然后,事务 1 需要 Part 表的锁,但无法获得锁,因为事务 2 将它锁定了。事务在提交或回滚之前不能释放持有的锁。因为事务需要对方控制的锁才能继续操作,所以它们不能提交或回滚。
死锁经常与正常阻塞混淆。当一个事务锁定了另一个事务需要的资源,第二个事务等待锁被释放。默认情况下,SQL Server 事务不会超时(除非设置了 LOCK_TIMEOUT)。第二个事务被阻塞,而不是被死锁。
use master
go
declare @spid int,@bl int
declare s_cur cursor for
select 0 ,blocked
from (select * from sysprocesses where blocked>0 ) a
where not exists(select * from (select * from sysprocesses where blocked>0 ) b where a.blocked=spid)
union
select spid,blocked from sysprocesses where blocked>0
open s_cur
fetch next from s_cur into @spid,@bl
while @@fetch_status = 0
begin
if @spid =0
select N'引起数死鎖的是:'+ltrim(@bl)+N'进程号,其执SQL语法如下'
else
select N'进程号:'+ ltrim(@bl)+N'被'+N'进程号:'+ltrim(@bl)+N'阻塞,其当前进 进程執行的SQL语法如下:'
dbcc inputbuffer (@bl )
fetch next from s_cur into @spid,@bl
end
close s_cur
deallocate s_cur
(2.3) 获取连接SQL服务器的信息
if object_id('p_getlinkinfo','P')is not null drop proc p_getlinkinfo
go
create proc p_getlinkinfo
@dbname sysname=null, --要查詢的數據庫名,默認表示所有
@includeip bit=0 --是否顯示IP信息
as
begin
declare @dbid int
set @dbid=db_id(@dbname)
if object_id('tempdb..#tb')is not null drop table #tb
if object_id('tempdb..#ip')is not null drop table #ip
create table #tb
(id int identity(1,1),
dbname sysname,
hostname nchar(128),
loginname nchar(128),
net_address nchar(12),
net_ip nvarchar(15),
prog_name nchar(128))
insert into #tb(hostname,dbname,net_address,loginname,prog_name)
select distinct hostname,
db_name(dbid),
net_address,
loginame,
program_name
from master..sysprocesses
where hostname!=''and(@dbid is null or dbid=@dbid)
if @includeip=0 goto lb_show --不顯示IP
declare @sql varchar(500),@hostname nchar(128),@id int
create table #ip(hostname nchar(128),a varchar(200))
declare tb cursor local for select distinct hostname from #tb
open tb
fetch next from tb into @hostname
while @@fetch_status=0
begin
set @sql='ping '+@hostname+' -a -n 1 -l 1'
insert #ip(a) exec master..xp_cmdshell @sql
update #ip set hostname=@hostname where hostname is null
fetch next from tb into @hostname
end
update #tb set net_ip=left(a,patindex('%:%',a)-1)
from #tb a inner join
(select hostname,a=substring(a,patindex('Ping statistics for %:%',a)+20,20)
from #ip
where a like'Ping statistics for %:%')b
on a.hostname=b.hostname
lb_show:
select id,
dbname,
hostname,
loginname,
net_address,
net_ip,
prog_name
from #tb
end
go
exec p_getlinkinfo @dbname='DB_WIP',@includeip=1