We are having an occasional problem occur where a
process will not stop blocking.
We are trying to trace the problem, but in the interim,
I would like to set up an alert that notifies me when a
process has been blocking for too long.
Are any of the lock wait times good statistics to use
for such an alert? If not, is there anything else I could
look at from the alert level?
If I had to, I could periodically create a table of
sysprocess spids that are at the top of blocking chains,
then test for a spid that lingers. I'm hoping I can
avoid this and use the built-in monitoring instead, though.
Thanks!
GeoffWe're also monitoring open transactions kept for a specific threshold, depending on an app. In addition, look at sp_monitor system stored procedure and you may get some ideas on what and how it can be accomplished.|||What information do you have so far concerning the locking issue - how long is it blocking, how did you discover that blocking was occuring ... ?|||Thanks, rdjabarov. Active Transactions is a good idea, since they
don't ever seem to build up higher than 4 or 5, if today's performance
monitor results can be trusted.
rnealjr:
When we encounter the problem, the blocking processes seem like
they would continue blocking perpetually. The only thing I can do to
solve the situation is to go in and kill the offending process. I am
trying to address the reason this occurs, but in the meantime I need
to fix it by brute force.
We are running a Java application that accesses the data using
a CORBA-based middle tier (Versata, in case you've heard of it).
The CORBA objects use the MS JDBC driver to hit the database,
which is MS SQL 2000.
I just tried upgrading the driver to sp2 and SQL to sp3a last night.
Things were going well this morning, but I think I caused some
trouble when I ran DBCC SHOWCONTIG while following a performance
tuning doc.
Anyway, I figured I'd show an example of an offending process,
obtained by using sp_blocker_pss80:
========================================
SPID: 144
STATUS: sleeping
BOLCKED: 0
OPEN_TRAN: 1
WAITRESOURCE: 8:1:269596
WAITTYPE: 0x0000
WAITTIME: 0
CMD: AWAITING COMMAND
LATWAITTYPE: PAGEIOLATCH_SH
CPU: 30
PHYSICAL_IO: 26
MEMUSAGE: 26
LASTBATCH: 2004-01-14 08:48:28.003
LOGINTIME: 2004-01-14 08:41:00.490
NETADDRESS 000000000000
NET_LIBRARY: TCP/IP
DBID: 8
ECID: 0
KPID: 0
HOSTNAME: spnvls00.na01.crl.com
HOSTPROCESS: 0
LOGINNAME: ilims
PRGRAMNAME:
NT_DOMAIN:
NT_USERNAME:
UID: 1
SID: 0xCDEB103BDA944A418B51092B9253F78D...
SQL_HANDLE: 0x0000000000000000000000000000000000000000
STMT_START: 0
STMT_END: 0
========================================
The thing I find weird, although a more experienced eye may not, is
that it's sleeping and "AWAITING COMMAND", yet it still has 1 open
transaction. It seems to me like this kind of situation could cause
a lingering block.
Thanks again!|||99% of the time it IS the main reason for blocking, along with long running transactions.|||When this happens again, you can use enterprise manager. Go to management -> current activity -> locks/processid - this will help you locate the process that is blocking and will show all the lock information associated with that process. Open that process - that will show up to 255 characters what action is causing the block which will help you locate what/where the problem is. Always make sure that you refresh the "current activity" first - otherwise, you might be looking at old process info. Once you have the information you need, then kill the process.|||Below is the script I've been using since 6.5 version to identify the blocking chain:
set statistics time off
set nocount on
set statistics io off
if charindex('6.5', @.@.version) = 0 begin
exec ('set statistics profile off')
end
--go
select
spid,
BlockedBy=blocked,
Status=convert(char(10), status),
DBName=convert(varchar(20), db_name(dbid)),
Host=convert(varchar(20), hostname),
Program=convert(varchar(40), program_name),
LoggedIn=convert(char(10), login_time, 101) + ' ' + convert(varchar(12), login_time, 114),
LastBatch=convert(char(10), last_batch, 101) + ' ' + convert(varchar(12), last_batch, 114)
from master.dbo.sysprocesses blocker (NOLOCK)
WHERE Exists (
select
spid,
blocked,
status,
DBName=convert(varchar(20), db_name(dbid)),
Host=convert(varchar(20), hostname),
Program=convert(varchar(40), program_name),
LoggedIn=convert(char(10), login_time, 101) + ' ' + convert(varchar(12), login_time, 114),
LastBatch=convert(char(10), last_batch, 101) + ' ' + convert(varchar(12), last_batch, 114)
from master.dbo.sysprocesses victim (NOLOCK)
where blocker.spid = victim.blocked)
UNION
select
spid,
blocked,
Status=convert(char(10), status),
DBName=convert(varchar(20), db_name(dbid)),
Host=convert(varchar(20), hostname),
Program=convert(varchar(40), program_name),
LoggedIn=convert(char(10), login_time, 101) + ' ' + convert(varchar(12), login_time, 114),
LastBatch=convert(char(10), last_batch, 101) + ' ' + convert(varchar(12), last_batch, 114)
from master.dbo.sysprocesses blocker (NOLOCK)
where blocked != 0
ORDER BY blocked, spid
begin tran
create table #tmp (spid int null, BlockedBy int null)
commit tran
insert #tmp (spid, BlockedBy) select spid, BlockedBy from (
select
spid,
BlockedBy=blocked,
DBName=convert(varchar(30), db_name(dbid)),
Host=convert(varchar(30), hostname),
Program=convert(varchar(50), program_name),
LoggedIn=convert(char(10), login_time, 101) + ' ' + convert(varchar(12), login_time, 114),
LastBatch=convert(char(10), last_batch, 101) + ' ' + convert(varchar(12), last_batch, 114)
from master.dbo.sysprocesses blocker (NOLOCK)
WHERE Exists (
select
spid,
blocked,
DBName=convert(varchar(30), db_name(dbid)),
Host=convert(varchar(30), hostname),
Program=convert(varchar(50), program_name),
LoggedIn=convert(char(10), login_time, 101) + ' ' + convert(varchar(12), login_time, 114),
LastBatch=convert(char(10), last_batch, 101) + ' ' + convert(varchar(12), last_batch, 114)
from master.dbo.sysprocesses victim (NOLOCK)
where blocker.spid = victim.blocked)
UNION
select
spid,
blocked,
DBName=convert(varchar(30), db_name(dbid)),
Host=convert(varchar(30), hostname),
Program=convert(varchar(50), program_name),
LoggedIn=convert(char(10), login_time, 101) + ' ' + convert(varchar(12), login_time, 114),
LastBatch=convert(char(10), last_batch, 101) + ' ' + convert(varchar(12), last_batch, 114)
from master.dbo.sysprocesses blocker (NOLOCK)
where blocked != 0 ) x
ORDER BY blockedby, spid
if @.@.rowcount > 0 begin
set nocount on
declare @.spid int, @.cmd varchar(255), @.cmd1 varchar(255)
select @.spid = min(spid) from #tmp where BlockedBy = 0
while @.spid is not null begin
select @.cmd = 'dbcc inputbuffer(' + convert(varchar(25), @.spid) + ')'
set @.cmd1= '!!!!!!!!!!!!!!!!!INPUTBUFFER information for blocking SPID ' + convert(varchar(25), @.spid) + ':'
print ''
print '************************************************* ***************************************'
print @.cmd1
print '************************************************* ***************************************'
exec (@.cmd)
-- print '************************************************* ***************************************'
print ''
select @.spid = min(spid) from #tmp where BlockedBy = 0 and spid > @.spid
end
print '************************************************* ****************************************'
print ''
print 'LIST OF AFFECTED PROCESSES'
print '**************************'
select @.spid = min(spid) from #tmp
while @.spid is not null begin
select @.cmd = 'dbcc inputbuffer(' + convert(varchar(25), @.spid) + ')'
select @.cmd1= 'INPUTBUFFER informtion for SPID ' + convert(varchar(25), @.spid) + ':'
print @.cmd1
exec (@.cmd)
print ''
select @.spid = min(spid) from #tmp where spid > @.spid
end
end else
print 'No blocking detected!'
go
drop table #tmp
go
No comments:
Post a Comment