I'm currently hunting down an issue we have with deadlocks and SQL Server. There are quite a lot of deadlocks occurring. The following deadlock graph is what I am focusing on (from the live environment):
<deadlock>
<victim-list>
<victimProcess id="process41fce08"/>
<victimProcess id="process40c9048"/>
</victim-list>
<process-list>
<process id="process41fce08" taskpriority="0" logused="0" waitresource="KEY: 5:72057595257749504 (03e6337489b1)" waittime="2133" ownerId="213210603" transactionname="SELECT" lasttranstarted="2015-09-30T09:06:29.133" XDES="0xe1d9dcb0" lockMode="RangeS-S" schedulerid="4" kpid="3608" status="suspended" spid="113" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2015-09-30T09:06:29.133" lastbatchcompleted="2015-09-30T09:06:29.133" clientapp=".Net SqlClient Data Provider" hostname="MYSERVER" hostpid="1692" loginname="MYUSER" isolationlevel="serializable (4)" xactid="213210603" currentdb="5" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
<executionStack>
<frame procname="" line="25" stmtstart="1876" stmtend="5346" sqlhandle="0x030005007f7dca111202de0024a400000100000000000000"/>
</executionStack>
<inputbuf> Proc [Database Id = 5 Object Id = 298483071] THIS IS READ STORED PROCEDURE </inputbuf>
</process>
<process id="process40c9048" taskpriority="0" logused="0" waitresource="KEY: 5:72057595257749504 (03e6337489b1)" waittime="2137" ownerId="213210579" transactionname="SELECT" lasttranstarted="2015-09-30T09:06:29.130" XDES="0x8051fcb0" lockMode="RangeS-S" schedulerid="2" kpid="3908" status="suspended" spid="101" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2015-09-30T09:06:29.130" lastbatchcompleted="2015-09-30T09:06:29.130" clientapp=".Net SqlClient Data Provider" hostname="MYSERVER" hostpid="5328" loginname="MYUSER" isolationlevel="serializable (4)" xactid="213210579" currentdb="5" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
<executionStack>
<frame procname="" line="25" stmtstart="1876" stmtend="5346" sqlhandle="0x030005007f7dca111202de0024a400000100000000000000"/>
</executionStack>
<inputbuf> Proc [Database Id = 5 Object Id = 298483071] THIS IS READ STORED PROCEDURE </inputbuf>
</process>
<process id="process11eca3708" taskpriority="0" logused="247980" waitresource="OBJECT: 5:1745427475:0 " waittime="1913" ownerId="213208999" transactionname="user_transaction" lasttranstarted="2015-09-30T09:06:28.640" XDES="0xc2f3ae90" lockMode="IX" schedulerid="3" kpid="272" status="suspended" spid="72" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2015-09-30T09:06:29.410" lastbatchcompleted="2015-09-30T09:06:29.410" clientapp=".Net SqlClient Data Provider" hostname="MYSERVER" hostpid="4172" loginname="MYUSER" isolationlevel="serializable (4)" xactid="213208999" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="" line="6" stmtstart="232" sqlhandle="0x0300050098df89558d028500b59f00000100000000000000"/>
</executionStack>
<inputbuf> Proc [Database Id = 5 Object Id = 1435099032] THIS IS READ UPDATE PROCEDURE </inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057595257749504" dbid="5" objectname="" indexname="" id="lockee29f480" mode="X" associatedObjectId="72057595257749504">
<owner-list/>
<waiter-list>
<waiter id="process41fce08" mode="RangeS-S" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057595257749504" dbid="5" objectname="" indexname="" id="lockee29f480" mode="X" associatedObjectId="72057595257749504">
<owner-list>
<owner id="process11eca3708" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process40c9048" mode="RangeS-S" requestType="wait"/>
</waiter-list>
</keylock>
<objectlock lockPartition="0" objid="1745427475" subresource="FULL" dbid="5" objectname="" id="lock128d27d80" mode="S" associatedObjectId="1745427475">
<owner-list>
<owner id="process41fce08" mode="S"/>
</owner-list>
<waiter-list>
<waiter id="process11eca3708" mode="IX" requestType="convert"/>
</waiter-list>
</objectlock>
</resource-list>
</deadlock>
Looking at deadlock victim process id = process41fce08, which is a select stored procedure, appears to run under a Serializable transaction.
However, looking at the stack trace, the transaction scope is not used. No explicit transaction is created. A simple SqlConnection and SqlCommand is used to execute the stored procedure.
Looking at the call stack to execute the same code path on my local development machine this shows the transaction isolation level running under ReadCommitted. This information is retrieved using:
select
CASE transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'ReadUncommitted'
WHEN 2 THEN 'ReadCommitted'
WHEN 3 THEN 'Repeatable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot'
ELSE 'Unknown'
END
FROM sys.dm_exec_sessions
where session_id = @@SPID
from inside the stored procedure. If I call:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
in the stored procedure, I see the isolation level change in the above select. This is what I expect and what I see in my development environment:
Default Isolation Level in ADO.NET
So given that:
- TransactionScope does not get set in the call stack
- No isolation level is set inside the stored procedure
Something appears to be setting the Isolation Level on the live environment? The question is what is setting this or forcing it to be Serializable?
The code runs in a MVC3 Application on .NET 4.