最近公司的數據庫並發有點大,由於CPU不高、內存不高、硬盤正常、網絡也正常等等,但系統還是會卡,所以就懷疑是數據庫阻塞導致的,於是去查詢資料,看書及經過用以下sql觀查,經過幾天對數據的分析找到原因並解決后,在這里分享下。
一、准備知識
需要了解數據阻塞的基本知識,了解數據庫常見鎖的運行機制,有了這個基礎后,對下面的sql執行的結果可以更加的了解,在使用以下sql時,准備這些知識是很重要的。
二、查看當前阻塞
運行 sp_lock 或
select spid,blocked,cmd,waittime,lastwaittype,waittype,waitresource,dbid,uid,cpu,physical_io,memusage,login_time,last_batch, open_tran,status,hostname,program_name,net_library,loginame from sysprocesses where blocked>0
三、查看數據庫當前鎖的情況
select request_session_id,resource_type,resource_associated_entity_id,request_status,request_mode,resource_description,p.object_id,object_name(P.OBJECT_ID) as object_name,p.* from sys.dm_tran_locks left join sys.partitions p on sys.dm_tran_locks.resource_associated_entity_id=p.hobt_id where resource_database_id=db_id('數據庫名') order by request_session_id,resource_type,resource_associated_entity_id
四、捕獲數據庫阻塞情況,將以下代碼保存成sql文本件
/* sqlcmd -E -S . -i 捕獲數據庫阻塞情況.sql -w2000 -o log.out */ use master go while 1=1 begin print 'Start time:'+convert(varchar(26),getdate(),121) print 'Running processes' select spid,blocked,waittype,waittime,lastwaittype,waitresource,dbid,uid,cpu,physical_io,memusage,login_time,last_batch, open_tran,status,hostname,program_name,cmd,net_library,loginame from sysprocesses --where(ipid<>0) or(spid<51) --Change it if you only want to see the working processes print '*****lockinfo*****' select convert(smallint,req_spid) as spid, rsc_dbid as dbid, rsc_objid as objid, rsc_indid as indid, substring(v.name,1,4) as type, substring(rsc_text,1,16) as resource, substring(u.name,1,8) as mode, substring(x.name,1,5) as status from master.dbo.syslockinfo, master.dbo.spt_values v, master.dbo.spt_values x, master.dbo.spt_values u where master.dbo.syslockinfo.rsc_type=v.number and v.type='LR' and master.dbo.syslockinfo.req_status=x.number and x.type='LS' and master.dbo.syslockinfo.req_mode+1=u.number and u.type='L' order by spid print 'inputbuffer for running processes' declare @spid varchar(6) declare ibuffer cursor fast_forward for select cast(spid as varchar(6)) as spid from sysprocesses where spid>50 open ibuffer fetch next from ibuffer into @spid while (@@FETCH_STATUS!=-1) begin print '' print 'DBCC inputbuffer for spid '+@spid exec ('dbcc inputbuffer('+@spid+')') fetch next from ibuffer into @spid end deallocate ibuffer waitfor delay '0:0:10' end
代碼每隔10秒運行一次。
在cmd里運行以下命令,會在當前目錄里產生一個log.out,可能用editplus查看此日志,日志對鎖的申請和占用都有詳細的記錄,可以量大的話可以每天重新運行。
sqlcmd -E -S . -i 捕獲數據庫阻塞情況.sql -w2000 -o log.out
PS:以上的代碼大多都由《SQL Server 2012 實施與管理實戰指南》上來的,還是非常實用的,這本書買了有一段時間,碰到問題了就起來來翻翻。
完畢