I have an application that simultaneously runs several sql statements in different threads, causing various deadlocks that seem to come from the same table. For example, two update statements below:
UPDATE WF SET QUEUETIME = '2011-02-18 13: 06: 53.578', STATE = 'outbound', USER = '', TIME = null WHERE PID = 'MessageProcessing' AND ACTIVITYID = 'Delete' AND ITEMID = '120' AND TRANID = 'Created' AND STATE = 'ready' AND USER = ''
UPDATE WF SET QUEUETIME = '2011-02-18 13: 06: 53.625', STATE = 'ready', USER = '', TIME = null WHERE PID = 'standardOutbound' AND ACTIVITYID = 'Node1' AND ITEMID = '121' AND TRANID = 'toNode1' AND STATE = '' AND USER = ''
produces the following deadlock:
<deadlock-list> <deadlock victim="process6d8e38"> <process-list> <process id="process6d8e38" taskpriority="0" logused="272" waitresource="RID: 7:1:564:14" waittime="625" ownerId="430343" transactionname="implicit_transaction" lasttranstarted="2011-02-18T13:06:53.640" XDES="0xb44a258" lockMode="U" schedulerid="1" kpid="2632" status="suspended" spid="58" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2011-02-18T13:06:53.640" lastbatchcompleted="2011-02-18T13:06:53.640" clientapp="jTDS" hostname="INTERWOV-FP1" hostpid="123" loginname="database1" isolationlevel="read committed (2)" xactid="430343" currentdb="7" TIMEout="4294967295" clientoption1="671088672" clientoption2="128058"> <executionStack> <frame procname="adhoc" line="1" stmtstart="336" sqlhandle="0x0200000077e2b21749c20d3ca2ca8d4d89ea5ea29336e03e"> UPDATE WF SET QUEUETIME = @P0 , STATE = @P1 , USER = @P2 , TIME = @P3 WHERE PID = @P4 AND ACTIVITYID = @P5 AND ITEMID = @P6 AND TRANID = @P7 AND STATE = @P8 AND USER = @P9 </frame> </executionStack> <inputbuf> (@P0 datetime,@P1 nvarchar(4000),@P2 nvarchar(4000),@P3 datetime,@P4 nvarchar(4000),@P5 nvarchar(4000),@P6 int,@P7 nvarchar(4000),@P8 nvarchar(4000),@P9 nvarchar(4000))UPDATE WF SET QUEUETIME = @P0 , STATE = @P1 , USER = @P2 , TIME = @P3 WHERE PID = @P4 AND ACTIVITYID = @P5 AND ITEMID = @P6 AND TRANID = @P7 AND STATE = @P8 AND USER = @P9 </inputbuf> </process> <process id="process8ccb68" taskpriority="0" logused="900" waitresource="RID: 7:1:564:12" waittime="625" ownerId="430341" transactionname="implicit_transaction" lasttranstarted="2011-02-18T13:06:53.623" XDES="0xaeccf48" lockMode="U" schedulerid="2" kpid="312" status="suspended" spid="53" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2011-02-18T13:06:53.640" lastbatchcompleted="2011-02-18T13:06:53.623" clientapp="jTDS" hostname="INTERWOV-FP1" hostpid="123" loginname="database1" isolationlevel="read committed (2)" xactid="430341" currentdb="7" TIMEout="4294967295" clientoption1="671088672" clientoption2="128058"> <executionStack> <frame procname="adhoc" line="1" stmtstart="336" sqlhandle="0x0200000077e2b21749c20d3ca2ca8d4d89ea5ea29336e03e"> UPDATE WF SET QUEUETIME = @P0 , STATE = @P1 , USER = @P2 , TIME = @P3 WHERE PID = @P4 AND ACTIVITYID = @P5 AND ITEMID = @P6 AND TRANID = @P7 AND STATE = @P8 AND USER = @P9 </frame> </executionStack> <inputbuf> (@P0 datetime,@P1 nvarchar(4000),@P2 nvarchar(4000),@P3 datetime,@P4 nvarchar(4000),@P5 nvarchar(4000),@P6 int,@P7 nvarchar(4000),@P8 nvarchar(4000),@P9 nvarchar(4000))UPDATE WF SET QUEUETIME = @P0 , STATE = @P1 , USER = @P2 , TIME = @P3 WHERE PID = @P4 AND ACTIVITYID = @P5 AND ITEMID = @P6 AND TRANID = @P7 AND STATE = @P8 AND USER = @P9 </inputbuf> </process> </process-list> <resource-list> <ridlock fileid="1" pageid="564" dbid="7" objectname="database1.dbo.WF" id="lock3a63dc0" mode="X" associatedObjectId="72057594077577216"> <owner-list> <owner id="process6d8e38" mode="X"/> </owner-list> <waiter-list> <waiter id="process8ccb68" mode="U" requestType="wait"/> </waiter-list> </ridlock> <ridlock fileid="1" pageid="564" dbid="7" objectname="database1.dbo.WF" id="lock3a65f40" mode="X" associatedObjectId="72057594077577216"> <owner-list> <owner id="process8ccb68" mode="X"/> </owner-list> <waiter-list> <waiter id="process6d8e38" mode="U" requestType="wait"/> </waiter-list> </ridlock> </resource-list> </deadlock> </deadlock-list>
I understand that some locks are inevitable, and the application must handle them (what it does), but I do not understand why they should occur in this case. In my simplified mind, these two statements should block different lines, and even if they update the same line, you just have to wait for the other.
Can someone explain why they cause deadlocks, or give any suggestions on how to prevent them?
We have 3 non-clustered indexes in the table (PID, ACTIVITYID, ITEMID, TRANID), (ITEMID) and (PID, ACTIVITYID). (PID, ACTIVITYID, ITEMID, TRANID) form the primary key. I tried (somewhat blindly) to play with indexes, but seemingly to no avail.
The application runs on weblogic and sql server 2005, and I reproduced the deadlocks on websphere and sql server 2008. It seems that this does not happen when using the oracle database, but this, unfortunately, is not an option for our client!
Many thanks to everyone who can help or understand this.