(Reprint) Find out and fixing deadlock by sql server 2005 immediately
2009-07-06 19:00
507 查看
reprint from: http://weblogs.sqlteam.com/mladenp/archive/2008/05/21/SQL-Server-2005-Immediate-Deadlock-notifications.aspx
This article is focusing on about using Sql Server 2005's features to find out and handling deadlock problems.1, Try Catch2, After Catch Exception, checkingXACT_STATE() = -1 // transaction has uncommitted3, After that then checking
ERROR_NUMBER() = 1205 // deadlockDeadlocks can be a pain to debug since they're so rare andunpredictable. The problem lies in repeating them in your devenvironment. That's why it's crucial to have as much information aboutthem from the production environment as possible.There are two ways to monitor deadlocks, about which I'll talk aboutin the future posts. Those are SQL Server tracing and Error logchecking. Unfortunately both of them suffer from the same thing: youdon't know immediately when a deadlock occurs. Getting this info assoon as possible is sometimes crucial in production environments. Sureyou can always set the trace flag 1222 on, but this still doesn't solvethe immediate notification problem.One problem for some might be that this method is only truly usefulif you limit data access to stored procedures. <joke> So all youORM lovers stop reading since this doesn't apply to you anymore!</joke>The other problem is that it requires a rewrite of the problematicstored procedures to support it. However since SQL Server 2005 came outmy opinion is that every stored procedure should have the try ... catchblock implemented. There's no visible performance hit from this and thebenefits can be huge. One of those benefits are the instant deadlockingnotifications.Needed "infrastructure"So let's see how it done. This must be implemented in the database you wish to monitor of course.First we need a view that will get lock info about the deadlock thatjust happened. You can read why this type of query gives info we needin my previous post.CREATE VIEW vLocksASSELECT L.request_session_id AS SPID,DB_NAME(L.resource_database_id) AS DatabaseName,O.Name AS LockedObjectName,P.object_id AS LockedObjectId,L.resource_type AS LockedResource,L.request_mode AS LockType,ST.text AS SqlStatementText,ES.login_name AS LoginName,ES.host_name AS HostName,TST.is_user_transaction AS IsUserTransaction,AT.name AS TransactionNameFROM sys.dm_tran_locks LLEFT JOIN sys.partitions P ON P.hobt_id = L.resource_associated_entity_idLEFT JOIN sys.objects O ON O.object_id = P.object_idLEFT JOIN sys.dm_exec_sessions ES ON ES.session_id = L.request_session_idLEFT JOIN sys.dm_tran_session_transactions TST ON ES.session_id = TST.session_idLEFT JOIN sys.dm_tran_active_transactions AT ON TST.transaction_id = AT.transaction_idLEFT JOIN sys.dm_exec_requests ER ON AT.transaction_id = ER.transaction_idCROSS APPLY sys.dm_exec_sql_text(ER.sql_handle) AS STWHERE resource_database_id = db_id()GONext we have to create our stored procedure template:CREATE PROC <ProcedureName>ASBEGIN TRANBEGIN TRY<SPROC TEXT GOES HERE>COMMITEND TRYBEGIN CATCH-- check transaction stateIF XACT_STATE() = -1BEGINDECLARE @message xml-- get our deadlock info FROM the VIEWSET @message = '<TransactionLocks>' + (SELECT * FROM vLocks ORDER BY SPID FOR XML PATH('TransactionLock')) + '</TransactionLocks>'-- issue ROLLBACK so we don't ROLLBACK mail sendingROLLBACK-- get our error message and numberDECLARE @ErrorNumber INT, @ErrorMessage NVARCHAR(2048)SELECT @ErrorNumber = ERROR_NUMBER(), @ErrorMessage = ERROR_MESSAGE()-- if it's deadlock error send mail notificationIF @ErrorNumber = 1205BEGINDECLARE @MailBody NVARCHAR(max)-- create out mail body in the xml format. you can change this to your liking.SELECT @MailBody = '<DeadlockNotification>'+(SELECT 'Error number: ' + isnull(CAST(@ErrorNumber AS VARCHAR(5)), '-1') + CHAR(10) +'Error message: ' + isnull(@ErrorMessage, ' NO error message') + CHAR(10)FOR XML PATH('ErrorMeassage'))+CAST(ISNULL(@message, '') AS NVARCHAR(MAX))+'</DeadlockNotification>'-- for testing purposes-- SELECT CAST(@MailBody AS XML)-- send an email with the defined email profile.-- since this is async it doesn't halt executionEXEC msdb.dbo.sp_send_dbmail@profile_name = 'your mail profile',@recipients = 'dba@yourCompany.com',@subject = 'Deadlock occured notification',@body = @MailBody;ENDENDEND CATCHGOThe main part of this stored procedure is of course the CATCH block. The first line in there is check of the XACT_STATE()value. This is a scalar function that reports the user transactionstate. -1 means that the transaction is uncommittable and has to berolled back. This is the state of the victim transaction in theinternal deadlock killing process. Next we read from our vLocks view toget the full info (SPID, both SQL statements text, values, etc...)about both SPIDs that created a deadlock. This is possible since ourdeadlock victim transaction hasn't been rolled back yet and the locksare still present. We save this data into an XML message. Next werollback our transaction to release locks. With error message and it'scorresponding number we check if the error is 1205 - deadlock and if itis we send our message in an email. How to configure database mail canbe seen here.Both the view and the stored procedures template can and probably should be customized to suit your needs.Testing the theoryLet's try it out and see how it works with a textbook deadlock example that you can find in every book or tutorial.-- create our deadlock table with 2 simple rowsCREATE TABLE DeadlockTest ( id INT)INSERT INTO DeadlockTestSELECT 1 UNION ALLSELECT 2GONext create two stored procedures (spProc1 and spProc2) with our template:For spProc1 replace <SPROC TEXT GOES HERE> in the template with:UPDATE DeadlockTestSET id = 12WHERE id = 2-- wait 5 secs TO SET up deadlock condition IN other windowWAITFOR DELAY '00:00:05'UPDATE DeadlockTestSET id = 11WHERE id = 1For spProc2 replace <SPROC TEXT GOES HERE> in the template with:UPDATE DeadlockTestSET id = 11WHERE id = 1-- wait 5 secs TO SET up deadlock condition IN other windowWAITFOR DELAY '00:00:05'UPDATE DeadlockTestSET id = 12WHERE id = 2Next open 2 query windows in SSMS:In window 1 run put this script:exec spProc1In window 2 put this script:exec spProc2Run the script in the first window and after a second or two runthe script in the second window. A deadlock will happen and a fewmoments after the victim transaction fails you should get thenotification mail. Mail profile has to be properly configured ofcourse.The resulting email should contain an XML with full info about thedeadlock. You can view it by commenting msdb.dbo.sp_send_dbmailexecution and uncommenting the SELECT CAST(@MailBody AS XML) line.
相关文章推荐
- Find out distributor and publisher info in Sql Server replication (摘)
- How to find out the Sql Server version and service pack
- Beginning Transact-SQL With SQL Server 2000 and 2005 by Paul Turley
- Caused by: java.sql.SQLException: Out of memory; restart server and try again (needed 142328 bytes)
- Professional ADO.NET 2: Programming with SQL Server 2005, Oracle, and MySQL by Wallace B. McClure
- MCITP Developer: Microsoft SQL Server 2005 Data Access Design and Optimization Study Guide
- Microsoft SQL Server(TM) 2005 Implementation and Maintenance
- [转]各种分页 in SQL Server 2005, SQL Server 2000, MS Access and MySQL
- Cannot connect to WMI provider.You do not have permission or the server is unreachable.Note that you can only manager SQL Server 2005 and later version with SQL Server Configuration Manager.Invalid namespace [0x8004100e]
- Oracle and MS SQL Server 2005
- Give the New PIVOT and UNPIVOT Commands in SQL Server 2005 a Whirl
- Beginning T-SQL with Microsoft SQL Server 2005 and 2008
- sql: MySQL and Microsoft SQL Server Stored Procedures IN, OUT using csharp code
- Determine SQL Server memory use by database and object
- Index Fragmentation Report in SQL Server 2005 and 2008
- Professional SQL Server 2005 CLR Programming: with Stored Procedures, Functions, Triggers, Aggregates and Types
- IT书讯 -- Inside Microsoft SQL Server 2005 Query Tuning and Optimization
- (Reprint)Simulating the sequence of Oracle in Sql Server by leveraging the identity
- Step by Step Guide to Add a SQL Job in SQL Server 2005
- Implementing and Maintaining Microsoft SQL Server 2005