5 – DBA as detective 140 Figure 5.11: Blocked SPIDs found using Automated Discovery query. You might decide that you would like to take this query, and make it into a stored procedure. You can then load it into a maintenance database on each server so that you have it always available. It also means that you can parameterize it to control its behavior. For example, you may decide that you do not want to execute the portion of the query that counts locks, which on a very busy system could take quite a bit of time. Listing 5.4 shows the code to create this stored procedure, named usp_Find_Problems, with a flag to execute the lock count portion based on need. USE [DBA_Rep] GO /****** Object: StoredProcedure [dbo].[usp_Find_Problems] Script Date: 06/22/2009 22:41:37 ******/ 5 – DBA as detective 141 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[usp_Find_Problems] ( @count_locks BIT = 1 ) AS SET NOCOUNT ON Count the locks IF @count_locks = 0 GOTO Get_Blocks ELSE IF @count_locks = 1 BEGIN CREATE TABLE #Hold_sp_lock ( spid INT, dbid INT, ObjId INT, IndId SMALLINT, Type VARCHAR(20), Resource VARCHAR(50), Mode VARCHAR(20), Status VARCHAR(20) ) INSERT INTO #Hold_sp_lock EXEC sp_lock SELECT COUNT(spid) AS lock_count, SPID, Type, CAST(DB_NAME(DBID) AS VARCHAR(30)) AS DBName, mode FROM #Hold_sp_lock GROUP BY SPID, Type, CAST(DB_NAME(DBID) AS VARCHAR(30)), MODE ORDER BY lock_count DESC, DBName, SPID, MODE Show any blocked or blocking processes Get_Blocks: CREATE TABLE #Catch_SPID ( 5 – DBA as detective 142 bSPID INT, BLK_Status CHAR(10) ) INSERT INTO #Catch_SPID SELECT DISTINCT SPID, 'BLOCKED' FROM master sysprocesses WHERE blocked <> 0 UNION SELECT DISTINCT blocked, 'BLOCKING' FROM master sysprocesses WHERE blocked <> 0 DECLARE @tSPID INT DECLARE @blkst CHAR(10) SELECT TOP 1 @tSPID = bSPID, @blkst = BLK_Status FROM #Catch_SPID WHILE( @@ROWCOUNT > 0 ) BEGIN PRINT 'DBCC Results for SPID ' + CAST(@tSPID AS VARCHAR(5)) + '( ' + RTRIM(@blkst) + ' )' PRINT ' ' PRINT '' DBCC INPUTBUFFER(@tSPID) SELECT TOP 1 @tSPID = bSPID, @blkst = BLK_Status FROM #Catch_SPID WHERE bSPID > @tSPID ORDER BY bSPID END END Listing 5.4: Statement to create usp_Find_Problems. 5 – DBA as detective 143 Executing usp_Find_Problems with no parameters will return the lock counts as well as the blocked and blocking SPIDs, whereas executing it with a value of 0 as the input parameter will exclude the lock counts. Figure 5.12 shows both executions in SSMS, using vertical tab groups. Figure 5.12: Executing the usp_Find_Problems stored procedure with parameters. Summary In this chapter I demonstrated how I go about detecting SQL Server problems in the form of excessive locking, and blocking. While this is a good start for the DBA detective, there is much more ground to cover. I mentioned CPU and I/O in this chapter only peripherally, as it relates to problem code. In the next chapter, I will continue on the path of analyzing performance issues, but will extend the topic to explain how to make sure you get notified immediately of performance, and other, issues. After all, if you do not know about the problem, you can't fix it. I would much rather be notified of a potential issue from a system that is monitoring such events than from an irate application user, or from the Help Desk. Granted, you will be hard pressed to totally escape emails from users and that is OK, generally they are understanding. It is their bosses that are not. If you can find and fix, or even just 5 – DBA as detective 144 report, an issue before anyone else, it appears that you are ahead of the game. And you are … you are a DBA after all. Now let's delve into performance monitoring and notifications for SQL Server before someone beats us to it. . procedure with parameters. Summary In this chapter I demonstrated how I go about detecting SQL Server problems in the form of excessive locking, and blocking. While this is a good start for. are a DBA after all. Now let's delve into performance monitoring and notifications for SQL Server before someone beats us to it. . and make it into a stored procedure. You can then load it into a maintenance database on each server so that you have it always available. It also means that you can parameterize it to control