September 9, 2005 at 6:48 pm
Can somebody help me analyze this problem... This SQL Server has a database behind an ASP application. The application handles many users. We are getting tons of deadlocks. I have captured Trace data as well as turned on trace 1204 which produced the following information. Mind you, this is a little sample of the many deadlocks occurring. What is this telling me? What is Key:12:905158370:1 (2000c500d465), and KEY: 12:905158370:1 (e7003231e2c1)?
Thank you, DBAs.
.. Printing deadlock information
spid3
spid3 Wait-for graph
spid3
spid3 Node:1
spid3 KEY: 12:905158370:1 (2000c500d465) CleanCnt:1 Mode: X Flags: 0x0
spid3 Grant List 2::
spid3 Owner:0x41c57640 Mode: X Flg:0x0 Ref:0 Life:02000000 SPID:206 ECID:0
spid3 SPID: 206 ECID: 0 Statement Type: SELECT Line #: 22
spid3 Input Buf: Language Event: exec usp_ValidateWebMember 'ngoldburt', 'natalya80'
spid3 Requested By:
spid3 ResType:LockOwner Stype:'OR' Mode: S SPID:222 ECID:0 Ec0x93FED540) Value:0xb27a4d20 Cost0/234)
spid3
spid3 Node:2
spid3 KEY: 12:905158370:1 (e7003231e2c1) CleanCnt:1 Mode: X Flags: 0x0
spid3 Grant List 3::
spid3 Owner:0x93859a40 Mode: X Flg:0x0 Ref:0 Life:02000000 SPID:222 ECID:0
spid3 SPID: 222 ECID: 0 Statement Type: SELECT Line #: 22
spid3 Input Buf: Language Event: exec usp_ValidateWebMember 'rayvazyan', 'prime'
spid3 Requested By:
spid3 ResType:LockOwner Stype:'OR' Mode: S SPID:206 ECID:0 Ec0x9667D540) Value:0x800ff500 Cost0/254)
spid3 Victim Resource Owner:
spid3 ResType:LockOwner Stype:'OR' Mode: S SPID:222 ECID:0 Ec0x93FED540) Value:0xb27a4d20 Cost0/234)
spid3
.. Printing deadlock information
spid3
spid3 Wait-for graph
spid3
spid3 Node:1
spid3 KEY: 12:905158370:1 (4800cbc59677) CleanCnt:1 Mode: X Flags: 0x0
spid3 Grant List 1::
spid3 Owner:0xbd8d1d20 Mode: X Flg:0x0 Ref:0 Life:02000000 SPID:229 ECID:0
spid3 SPID: 229 ECID: 0 Statement Type: SELECT Line #: 22
spid3 Input Buf: Language Event: exec usp_ValidateWebMember 'mcooper', 'mc1125'
spid3 Requested By:
spid3 ResType:LockOwner Stype:'OR' Mode: S SPID:206 ECID:0 Ec0x9667D540) Value:0x800ff500 Cost0/254)
spid3
spid3 Node:2
spid3 KEY: 12:905158370:1 (2000c500d465) CleanCnt:1 Mode: X Flags: 0x0
spid3 Grant List 2::
spid3 Owner:0x41c57640 Mode: X Flg:0x0 Ref:0 Life:02000000 SPID:206 ECID:0
spid3 SPID: 206 ECID: 0 Statement Type: SELECT Line #: 22
spid3 Input Buf: Language Event: exec usp_ValidateWebMember 'ngoldburt', 'natalya80'
spid3 Requested By:
spid3 ResType:LockOwner Stype:'OR' Mode: S SPID:229 ECID:0 Ec0x96605540) Value:0x57a7a560 Cost0/21C)
spid3 Victim Resource Owner:
spid3 ResType:LockOwner Stype:'OR' Mode: S SPID:229 ECID:0 Ec0x96605540) Value:0x57a7a560 Cost0/21C)
September 12, 2005 at 7:22 am
It looks like the procedure usp_ValidateWebMember is having problems when executed simultaneously by more than one connection.
You need to look at the code inside usp_ValidateWebMember in order to find what may be causing the deadlocks.
For the most parts, deadlocking is a design phenomenon - it happens when you have two different connections doing some procedure, but in reversal order to each other, so you end up with both waiting for resources to be released that is held by the other. This will never be resolved by just waiting, so when the server sees this, it kills one connection in order to let the other continue, and reports a deadlock in the log.
/Kenneth
September 12, 2005 at 9:26 am
/***********************************************************************************************************/
spid3 Wait-for graph
spid3
spid3 Node:1
spid3 KEY: 12:905158370:1 (2000c500d465) CleanCnt:1 Mode: X Flags: 0x0
spid3 Grant List 2::
spid3 Owner:0x41c57640 Mode: X Flg:0x0 Ref:0 Life:02000000 SPID:206 ECID:0
spid3 SPID: 206 ECID: 0 Statement Type: SELECT Line #: 22
spid3 Input Buf: Language Event: exec usp_ValidateWebMember 'ngoldburt', 'natalya80'
spid3 Requested By:
spid3 ResType:LockOwner Stype:'OR' Mode: S SPID:222 ECID:0 Ec0x93FED540) Value:0xb27a4d20 Cost0/234)
spid3
spid3 Node:2
spid3 KEY: 12:905158370:1 (e7003231e2c1) CleanCnt:1 Mode: X Flags: 0x0
spid3 Grant List 3::
spid3 Owner:0x93859a40 Mode: X Flg:0x0 Ref:0 Life:02000000 SPID:222 ECID:0
spid3 SPID: 222 ECID: 0 Statement Type: SELECT Line #: 22
spid3 Input Buf: Language Event: exec usp_ValidateWebMember 'rayvazyan', 'prime'
spid3 Requested By:
spid3 ResType:LockOwner Stype:'OR' Mode: S SPID:206 ECID:0 Ec0x9667D540) Value:0x800ff500 Cost0/254)
spid3 Victim Resource Owner:
spid3 ResType:LockOwner Stype:'OR' Mode: S SPID:222 ECID:0 Ec0x93FED540) Value:0xb27a4d20 Cost0/234)
spid3
/***********************************************************************************************************/
SPID: x ECID: x
Identifies the system process ID thread in cases of parallel processes. The entry SPID x ECID 0 represents the main thread, and SPID x ECID > 0 represents the sub-threads for the same SPID. In your case, it is the main thread in both.
Statement Type : Represents update, select, insert, delete, execute (SELECT in your case is because that is the statement that that spid was executing and was blocked on).
All the locks in your case are related to KEY.
KEY identifies the key range within an index on which a lock is held or requested.
-- Declare variables to use in this example.
DECLARE @id int, @type char(2),@msg varchar(80),
@indid smallint, @indname sysname, @status int,
@indkey int, @name varchar(30)
SELECT @id = id, @type = type, @name = 'carton_hdr'
FROM sysobjects
WHERE name = 'carton_hdr' and type = 'U'
-- Start printing the output information.
print 'Index information for the '+@name+' table'
print '---------------------------------------'
-- Loop through all indexes in the authors table.
-- Declare a cursor.
DECLARE i cursor
FOR
SELECT indid, name, status
FROM sysindexes
WHERE id = @id
-- Open the cursor and fetch next set of index information.
OPEN i
FETCH NEXT FROM i INTO @indid, @indname, @status
IF @@FETCH_STATUS = 0
PRINT ' '
-- While there are still rows to retrieve from the cursor,
-- find out index information and print it.
WHILE @@FETCH_STATUS = 0
BEGIN
SET @msg = NULL
-- Print the index name and the index number.
SET @msg = ' Index number ' + CONVERT(varchar, @indid)+
' is '+@indname
SET @indkey = 1
-- @indkey (equivalent to key_id in the syntax diagram of
-- INDEX_COL) can be from 1 to 16.
WHILE @indkey <= 16 and INDEX_COL(@name, @indid, @indkey)
IS NOT NULL
BEGIN
-- Print different information if @indkey <> 1.
IF @indkey = 1
SET @msg = @msg + ' on '
+ index_col(@name, @indid, @indkey)
ELSE
SET @msg = @msg + ', '
+ index_col(@name, @indid, @indkey)
SET @indkey = @indkey + 1
END
PRINT @msg
SET @msg = NULL
FETCH NEXT FROM i INTO @indid, @indname, @status
END
CLOSE i
DEALLOCATE i
/*****************************************************************************/
Two tables: TableA and TableB which are related by a foreign key relationship (See the script below).
DROP TABLE TABLEA
GO
ALTER TABLE TABLEA ADD CONSTRAINT PK_TABLEA PRIMARY KEY CLUSTERED (COL1)
GO
CREATE TABLE TABLEB (COL1 INT NOT NULL, COL2 VARCHAR(30) NOT NULL, COL3 VARCHAR(30))
GO
ALTER TABLE TABLEB ADD CONSTRAINT PK_TABLEB PRIMARY KEY CLUSTERED (COL1, COL2)
GO
ALTER TABLE TABLEB ADD CONSTRAINT FK_TABLEB_TO_TABLEA FOREIGN KEY (COL1) REFERENCES TABLEA (COL1)
GO
INSERT INTO TABLEA (COL1, COL2, COL3, COL4) VALUES (1, 'TEST', 1, 'TEST-SQL')
INSERT INTO TABLEA (COL1, COL2, COL3, COL4) VALUES (2, 'TEST2', 1, 'TEST-SQL2')
INSERT INTO TABLEA (COL1, COL2, COL3, COL4) VALUES (3, 'TEST3', 1, 'TEST-SQL3')
INSERT INTO TABLEB (COL1, COL2, COL3) VALUES (1, 'TEST', 'TEST-SQL')
GO
set cursor_close_on_commit off
set ansi_defaults off
BEGIN TRAN
UPDATE TABLEA SET COL4 = 'TEST-SQL1' WHERE COL1 = 2
--Do Not Commit Yet
set cursor_close_on_commit off
set ansi_defaults off
set transaction isolation level read uncommitted
begin tran
select * from tableA with (nolock) where col1 = 2
set lock_timeout 5000
INSERT INTO TABLEB (COL1, COL2, COL3) VALUES (2, 'TEST-MOD', 'TESTSQL1')
--you will get the lock timeout error after 5 seconds
--ROLLBACK
September 12, 2005 at 4:00 pm
Ken/Sharma, Thank you very much for your help.
And Sharma, your explanation on how to interpret the information was great!!!.
Phenomenal was your insight that too many rows are qualified by the SELECT statement and I believe that it is the root cause of this problem. As a result we have re-written the query and moved it into the pre-production environment. We also changed the index and maded it as a non-clustering index. It will be few days before we move the changes into production. I will let everybody know if these changes result in no deadlocks in our production environment.
Thank you very much.
Ben
September 13, 2005 at 9:45 am
You are welcome Ben.
Since you are operating under the default isolation level of READ COMMITTED, another thing that you may want to look into for your SELECT statement(s) is the usage of READPAST (reading past locked records) or NOLOCK (dirty reads) locking hints. That is necessary only if there is no other way of avoiding the contention (I have seen some cases like this in ERP applications)...and be aware of what those two locking hints do before/if you decide to use them. BOL has more information on these.
Hth
Viewing 5 posts - 1 through 4 (of 4 total)
You must be logged in to reply to this topic. Login to reply