November 25, 2008 at 9:26 am
For us poor folks that cannot afford good SQL monitoring tools...looking for a script or configure an alert when a block is greater than 5 minutes.
November 25, 2008 at 9:56 am
Start from http://support.microsoft.com/?kbid=271509
MJ
November 25, 2008 at 10:10 am
You can query the sys.dm_exec_requests for requests with a blocked_by that's not 0 and a wait_time exceeding your threshold.
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
November 25, 2008 at 12:38 pm
Thanks to both but I would like to automate this..I guess I am dreaming about turkey dinner
I cannot see putting this in as a job then I would have to schedule the job to run frequently.
I would like to establish the warning via the SQL Job Alert
Is that possible?
November 25, 2008 at 2:36 pm
First create a alert of type(SQL Server Event Alert) and then chose severity of 016(Misc. User Error) for all databases. Then specify message text as "Blocking Threshold" . Then finally to get information about the blocking events encapsulate the information provided by us in stored procedure and call that stored procedure under Response-->Execute job(create a job calling the stored procedure created above).
Configure appropriate operators whom you want to notify.
MJ
November 25, 2008 at 10:01 pm
Use following query:
select r.session_id, r.blocking_session_id, r.database_id, r.command, s.last_request_start_time, s.login_name, r.last_wait_type, r.status
from sys.dm_exec_requests r
join sys.dm_exec_sessions s on r.session_id = s.session_id
where (r.blocking_session_id > 0 and r.blocking_session_id <> r.session_id)
or r.session_id in (select session_id from sys.dm_exec_requests where blocking_session_id > 0 and blocking_session_id <> session_id)
or
SELECT spid, status, loginame=substring(loginame, 1, 12),
hostname=substring(hostname, 1, 12),
blk=CONVERT(char(3), blocked),
open_tran,dbname=substring(db_name(dbid),1,10),cmd,
waittype, waittime, last_batch
FROM master.dbo.sysprocesses
WHERE spid IN (SELECT blocked FROM master.dbo.sysprocesses) AND blocked=0
November 27, 2008 at 2:13 am
Or you can put this in an agent job if you're on 2000. /It's a bit rough and ready but it gets you most of the way there
CREATE PROCEDURE [dbo].[FindOpenTransactions] AS
DECLARE @emailAddress VARCHAR(128)
SET @emailAddress = -- Put your distribution list here
--Create the required Tables IF they do not exist
IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'u' and name = 'Open_transactions')
BEGIN
CREATE TABLE Open_transactions
(
spid int NULL,
login VARCHAR(32) NULL,
db VARCHAR(128) NULL,
hostname VARCHAR(64) NULL
)
END
IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'u' and name = 'Open_transactions_history')
BEGIN
CREATE TABLE dbo.Open_transactions_history
(
Found_Date datetime NULL,
spid int NULL,
login VARCHAR(32) NULL,
db VARCHAR(128) NULL,
hostname VARCHAR(64) NULL,
program_name VARCHAR(128) NULL,
sqlCommandVARCHAR(2000) NULL
)
END
CREATE TABLE #InputBuffer
(
eventtype nVARCHAR(30) NULL,
params int NULL,
eventinfo nVARCHAR(255) NULL
)
/*Get list of processes with open transactions on the server*/
DECLARE curOpenTransProcs CURSOR
FOR SELECT
spid,
dbid,
hostname,
loginame,
program_name,
sql_handle
FROM master..sysprocesses
WHERE Open_tran > 0
DECLARE @spid int, @hostname VARCHAR(64), @login VARCHAR(32), @cmd VARCHAR(4000), @database VARCHAR(128), @program_name VARCHAR(128), @dbid int, @spidlist VARCHAR(2000), @wehavedata int
DECLARE @sql_handle-2 binary(20)
DECLARE @sqlCommand VARCHAR(2000)
/*Set initial values for flag / spid list variables*/
SET @spidlist = ''
SET @wehavedata = 0
OPEN curOpenTransProcs
FETCH NEXT
FROM curOpenTransProcs
INTO @spid, @dbid, @hostname, @login, @program_name, @sql_handle-2
WHILE @@fetch_status = 0
BEGIN
SET @wehavedata = 1
SELECT @database = name FROM master..sysdatabases WHERE dbid = @dbid
/*which processes with open transactions have been active since the last check
(rather than bombard recipients with anything that's open at all)*/
IF EXISTS
(
SELECT spid FROM open_transactions
WHERE
spid = @spid
and
login = @login
and
db = @database
and
hostname = @hostname
)
BEGIN
/*Add current spid to the list of 'ones of interest'*/
SELECT @spidlist = @spidlist + CONVERT(VARCHAR(32), @spid) + ','
SELECT @sqlCommand = ''
-- IF @sql_handle-2 <> 0x0
-- BEGIN
/*Was originally going to try and take SQL command info from
::fn_get_sql - but wasn't getting anything back. This, in theory
should allow us to spot the exact locking statement from a batch -
but, doesn't appear to return any value if, say, the issue's caused by
a transaction where the work's complete but awaiting a rollback/commit
command (say being run manually through QA). So - use scruffy
DBCC INPUTBUFFER approach instead
*/
DELETE FROM #Inputbuffer
SELECT @cmd = 'DBCC INPUTBUFFER (' + STR(@spid) + ') WITH NO_INFOMSGS'
PRint @cmd
INSERT #Inputbuffer EXEC(@cmd)
SELECT @sqlCommand = COALESCE(RTRIM(EventInfo), 'Unable to identify SQL command')
FROM #InputBuffer
/*Keep a list of problematic transactions for future reference */
INSERT INTO Open_Transactions_History
(
Found_Date,
spid,
login,
db,
hostname,
program_name,
sqlCommand
)
VALUES
(
getdate(),
@spid,
@database,
@hostname,
@program_name,
@sqlCommand
)
/*Send warning e-mail to appropriate recipients*/
SELECT @cmd = 'Host: ' + @hostname + CHAR(13)
SELECT @cmd = @cmd + 'Login: ' + @login + CHAR(13)
SELECT @cmd = @cmd + 'Database: ' + @database + CHAR(13)
SELECT @cmd = @cmd + 'SPID: ' + CONVERT(VARCHAR(6), @spid) + CHAR(13)
SELECT @cmd = @cmd + 'Program: ' + CONVERT(VARCHAR(20), @program_name) + CHAR(13)
SELECT @cmd = @cmd + 'SQL: ' + CHAR(13) + @sqlCommand + CHAR(13) + CHAR(13)
SELECT @cmd = @cmd + 'Procedure : FindOpenTransactions' + CHAR(13) + CHAR(13)
EXEC master..xp_sendmail @recipients = @emailAddress, @subject = 'Open Transaction Notification', @message = @cmd
END
ELSE
/*If it's a new proc with open transactions add it to the 'watch list'*/
BEGIN
INSERT INTO open_transactions
(
spid,
login,
db,
hostname
)
VALUES
(
@spid,
@database,
@hostname
)
SELECT @spidlist = @spidlist + CONVERT(VARCHAR(32),@spid) + ','
END
FETCH NEXT FROM curOpenTransProcs INTO @spid, @dbid, @hostname, @login, @program_name, @sql_handle-2
END
--Cleanup
DROP TABLE #InputBuffer
PRINT 'spidlist ' + @spidlist
IF @wehavedata = 1
BEGIN
/*Remove anything from the open transactions table where the spid no longer exists on the server*/
SELECT @cmd = 'DELETE FROM Open_transactions
WHERE spid not in ('
+ SUBSTRING( @spidlist, 1, LEN(@spidlist) -1) + ')' + CHAR(13)
print @cmd
EXEC (@cmd)
END
ELSE
DELETE FROM Open_transactions
CLOSE curOpenTransProcs
DEALLOCATE curOpenTransProcs
GO
Viewing 7 posts - 1 through 6 (of 6 total)
You must be logged in to reply to this topic. Login to reply
This website stores cookies on your computer.
These cookies are used to improve your website experience and provide more personalized services to you, both on this website and through other media.
To find out more about the cookies we use, see our Privacy Policy