Deadlock issue in update statement in SQL Server - sql

I am facing a keylock deadlock issue in an update statement in SQL Server. I have a clustered index on the primary key and I am using them inside the where clause. I can say for sure that the 2 processes are not updating the same rows as the java code is written like that. They are trying to update different rows but still this deadlock is occurring. Both processes are owner mode of X and requesting for U lock as per the graph. I can share the other as well.
<deadlock-list>
<deadlock victim="process147029c28">
<process-list>
<process id="process147029c28" taskpriority="0" logused="1300"
waitresource="KEY: 7:72057600641925120 (ef40b100fec4)" waittime="6363"
ownerId="7750344" transactionname="implicit_transaction"
lasttranstarted="2018-10-25T21:52:35.553" XDES="0x10006ad90" lockMode="U"
schedulerid="3" kpid="17860" status="suspended" spid="67" sbid="0" ecid="0"
priority="0" trancount="2" lastbatchstarted="2018-10-25T21:52:36.567"
lastbatchcompleted="2018-10-25T21:52:36.540" lastattention="1900-01-
01T00:00:00.540" clientapp="Microsoft JDBC Driver for SQL Server"
hostname="USGURBHABISHT9" hostpid="0" loginname="bharat"
isolationlevel="read committed (2)" xactid="7750344" currentdb="7"
lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
</executionStack>
<inputbuf>
(#P0 nvarchar(4000),#P1 datetime2,#P2 nvarchar(4000),#P3 varchar(8000),#P4
varchar(8000),#P5 nvarchar(4000),#P6 nvarchar(4000),#P7 datetime2,#P8
nvarchar(4000),#P9 varchar(8000),#P10 nvarchar(4000),#P11
varchar(8000),#P12 bigint,#P13 varchar(8000),#P14 varchar(8000),#P15
nvarchar(4000),#P16 varchar(8000),#P17 datetime2,#P18 nvarchar(4000),#P19
nvarchar(4000),#P20 nvarchar(4000),#P21 varchar(8000),#P22
nvarchar(4000),#P23 nvarchar(4000),#P24 nvarchar(4000),#P25
nvarchar(4000),#P26 nvarchar(4000),#P27 nvarchar(4000),#P28 bigint,#P29
nvarchar(4000),#P30 nvarchar(4000),#P31 nvarchar(4000),#P32
nvarchar(4000),#P33 nvarchar(4000),#P34 nvarchar(4000))Update
IN_R_AU_MEM_ELIG_DTL set APPROVAL_CODE = #P0, ARCHIVE_DT = #P1,
CASE_NUMBER = #P2, CATEGORY_CODE = #P3, CG_STATUS_CODE = #P4, CLOSE_DATE =
#P5, CLOSURE_CODE = #P6, CREATE_DT = #P7, CREATE_USER_ID = #P8,
DELETE_INDICATOR = #P9, ELIGIBILITY_SEQUENCE_NUMBER = #P10,
ELIG_INCAR_FLAG = #P11, HISTORY_SEQ = #P12, INCARCERATION_CODE = #P13,
INCARCERATION_DISCHARGE_DATE = </inputbuf>
</process>
<process id="process13e98b088" taskpriority="0" logused="1992"
waitresource="KEY: 7:72057600641925120 (f128991fbbbb)" waittime="6349"
ownerId="7751290" transactionname="implicit_transaction"
lasttranstarted="2018-10-25T21:52:35.803" XDES="0x12f960d90" lockMode="U"
schedulerid="3" kpid="6176" status="suspended" spid="66" sbid="0" ecid="0"
priority="0" trancount="2" lastbatchstarted="2018-10-25T21:52:36.610"
lastbatchcompleted="2018-10-25T21:52:36.603" lastattention="1900-01-
01T00:00:00.603" clientapp="Microsoft JDBC Driver for SQL Server"
hostname="USGURBHABISHT9" hostpid="0" loginname="bharat"
isolationlevel="read committed (2)" xactid="7751290" currentdb="7"
lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
<inputbuf>
(#P0 nvarchar(4000),#P1 datetime2,#P2 nvarchar(4000),#P3 varchar(8000),#P4
varchar(8000),#P5 nvarchar(4000),#P6 nvarchar(4000),#P7 datetime2,#P8
nvarchar(4000),#P9 varchar(8000),#P10 nvarchar(4000),#P11
varchar(8000),#P12 bigint,#P13 varchar(8000),#P14 varchar(8000),#P15
nvarchar(4000),#P16 varchar(8000),#P17 datetime2,#P18 nvarchar(4000),#P19
nvarchar(4000),#P20 nvarchar(4000),#P21 varchar(8000),#P22
nvarchar(4000),#P23 nvarchar(4000),#P24 nvarchar(4000),#P25
nvarchar(4000),#P26 nvarchar(4000),#P27 nvarchar(4000),#P28 bigint,#P29
nvarchar(4000),#P30 nvarchar(4000),#P31 nvarchar(4000),#P32
nvarchar(4000),#P33 nvarchar(4000),#P34 nvarchar(4000))Update
IN_R_AU_MEM_ELIG_DTL set APPROVAL_CODE = #P0, ARCHIVE_DT = #P1,
CASE_NUMBER = #P2, CATEGORY_CODE = #P3, CG_STATUS_CODE = #P4, CLOSE_DATE =
#P5, CLOSURE_CODE = #P6, CREATE_DT = #P7, CREATE_USER_ID = #P8,
DELETE_INDICATOR = #P9, ELIGIBILITY_SEQUENCE_NUMBER = #P10,
ELIG_INCAR_FLAG = #P11, HISTORY_SEQ = #P12, INCARCERATION_CODE = #P13,
INCARCERATION_DISCHARGE_DATE = </inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057600641925120" dbid="7"
objectname="IEWP_EE.dbo.IN_R_AU_MEM_ELIG_DTL"
indexname="IN_R_AU_MEM_ELIG_DTL_PK" id="lock104f34d00" mode="X"
associatedObjectId="72057600641925120">
<owner-list>
<owner id="process13e98b088" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process147029c28" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057600641925120" dbid="7"
objectname="IEWP_EE.dbo.IN_R_AU_MEM_ELIG_DTL"
indexname="IN_R_AU_MEM_ELIG_DTL_PK" id="lock12ac42100" mode="X"
associatedObjectId="72057600641925120">
<owner-list>
<owner id="process147029c28" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process13e98b088" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
</resource-list>
</deadlock>
</deadlock-list>
Update statement:
Update table_name updating all the columns even the primary key
where 1=1
AND PERSON_NUMBER = '7769999750768'
AND TYPE_CASE_CODE = '550'
AND START_DATE = '20180901'
AND INCARCERATION_ADMIT_DATE = '00000000'
AND OSS_AMOUNT = '000'
AND AID_CATEGORY = '50'
Columns used in the where clause are the composite primary key.
And two update queries deadlocking are having different primary key values.
So how it can have a lock on primary key?
table schema:
CREATE TABLE [dbo].[IN_R_AU_MEM_ELIG_DTL](
[CREATE_USER_ID] [varchar](20) NOT NULL,
[CREATE_DT] [datetime] NOT NULL,
[UNIQUE_TRANS_ID] [bigint] NOT NULL,
[HISTORY_SEQ] [bigint] NOT NULL,
[RECORD_TYPE] [varchar](1) NULL,
[SUB_RECORD_TYPE] [varchar](1) NULL,
[RECORD_SEQUENCE] [varchar](9) NULL,
[PERSON_NUMBER] [varchar](13) NOT NULL,
[PERSON_SEQUENCE] [varchar](8) NULL,
[ELIGIBILITY_SEQUENCE_NUMBER] [varchar](5) NULL,
[CASE_NUMBER] [varchar](13) NULL,
[CATEGORY_CODE] [varchar](2) NULL,
[TYPE_CASE_CODE] [varchar](3) NOT NULL,
[START_DATE] [varchar](8) NOT NULL,
[CLOSE_DATE] [varchar](8) NULL,
[APPROVAL_CODE] [varchar](3) NULL,
[CLOSURE_CODE] [varchar](3) NULL,
[DELETE_INDICATOR] [varchar](1) NULL,
[INCARCERATION_CODE] [varchar](1) NULL,
[INCARCERATION_ADMIT_DATE] [varchar](8) NOT NULL,
[INCARCERATION_DISCHARGE_DATE] [varchar](8) NULL,
[INCARCERATION_ELIG_FLAG] [varchar](1) NULL,
[RENEWAL_DATE] [varchar](8) NULL,
[RENEWAL_CODE] [varchar](2) NULL,
[PRE_RELEASE_DATE] [varchar](8) NULL,
[LOCATION_CODE] [varchar](4) NULL,
[MONEY_CODE] [varchar](1) NULL,
[OSS_AMOUNT] [varchar](5) NOT NULL,
[AID_CATEGORY] [varchar](10) NOT NULL,
[CG_STATUS_CODE] [varchar](5) NULL,
[MMIS_SND_PERSON_SEQ_NUM] [varchar](15) NULL,
[PROCESS_SW] [varchar](1) NULL,
[ELIG_INCAR_FLAG] [varchar](1) NULL,
[ARCHIVE_DT] [datetime] NULL,
[ROWID] [uniqueidentifier] NOT NULL DEFAULT (newid()),
[MMIS_SND_DT] [datetime] NULL,
CONSTRAINT [IN_R_AU_MEM_ELIG_DTL_PK] PRIMARY KEY CLUSTERED
(
[INCARCERATION_ADMIT_DATE] ASC,
[AID_CATEGORY] ASC,
[OSS_AMOUNT] ASC,
[PERSON_NUMBER] ASC,
[START_DATE] ASC,
[TYPE_CASE_CODE] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

Related

Dead locking when accessing the same table

I have a C# application that works with data in a SQL Server table via stored procedures.
If 2 users execute a form copy at the same time the same procedure is executed where dead locking occurs
I got xml_deadlock_report in SQL Server under system_health. Here is what it looks like:
<deadlock>
<victim-list>
<victimProcess id="process10f2ea0188" />
</victim-list>
<process-list>
<process id="process10f2ea0188" taskpriority="0" logused="7424" waitresource="PAGE: 5:1:24768207 " waittime="83419" ownerId="61921962" transactionname="user_transaction" lasttranstarted="2022-06-21T05:40:40.083" XDES="0x6d4f80d28" lockMode="S" schedulerid="5" kpid="2392" status="suspended" spid="69" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2022-06-21T05:40:40.143" lastbatchcompleted="2022-06-21T05:40:40.083" lastattention="1900-01-01T00:00:00.083" clientapp=".Net SqlClient Data Provider" hostname="GKA" hostpid="12432" loginname="admin" isolationlevel="read committed (2)" xactid="61921962" currentdb="5" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128048">
<executionStack>
<frame procname="CreateSectionTable" line="28" stmtstart="2856" stmtend="2984" sqlhandle="0x030005005611575922a96e01ccad000001000000000000000000000000000000000000000000000000000000">
SELECT #nTableIndex = Max(DataTableIndex) + 1 FROM SectionTable </frame>
<frame procname="CopySectionInt" line="118" stmtstart="9900" stmtend="10098" sqlhandle="0x030005001e33f860a2a96e01ccad000001000000000000000000000000000000000000000000000000000000">
EXEC CreateSectionTable #SectionId, '', '', ''
/* копирование в него структуры столбцов */ </frame>
<frame procname="CopyForm" line="73" stmtstart="6408" stmtend="6530" sqlhandle="0x03000500acea0f5f7ea96e01ccad000001000000000000000000000000000000000000000000000000000000">
EXEC CopySectionInt #SectionID, #FormId, null, null </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 5 Object Id = 1594878636] </inputbuf>
</process>
<process id="process10ff03d498" taskpriority="0" logused="26216496" waitresource="PAGE: 5:1:23196243 " waittime="3894" ownerId="61920617" transactionname="user_transaction" lasttranstarted="2022-06-21T05:40:34.813" XDES="0x58a276d28" lockMode="S" schedulerid="6" kpid="4420" status="suspended" spid="66" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2022-06-21T05:40:34.817" lastbatchcompleted="2022-06-21T05:40:34.813" lastattention="1900-01-01T00:00:00.813" clientapp=".Net SqlClient Data Provider" hostname="SQLSER" hostpid="6120" loginname="SS\Bo" isolationlevel="read committed (2)" xactid="61920617" currentdb="5" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128048">
<executionStack>
<frame procname="CreateSectionTable" line="28" stmtstart="2856" stmtend="2984" sqlhandle="0x030005005611575922a96e01ccad000001000000000000000000000000000000000000000000000000000000">
SELECT #nTableIndex = Max(DataTableIndex) + 1 FROM SectionTable </frame>
<frame procname="CopySectionInt" line="118" stmtstart="9900" stmtend="10098" sqlhandle="0x030005001e33f860a2a96e01ccad000001000000000000000000000000000000000000000000000000000000">
EXEC CreateSectionTable #SectionId, '', '', ''
/* копирование в него структуры столбцов */ </frame>
<frame procname="CopyForm" line="73" stmtstart="6408" stmtend="6530" sqlhandle="0x03000500acea0f5f7ea96e01ccad000001000000000000000000000000000000000000000000000000000000">
EXEC CopySectionInt #SectionID, #FormId, null, null </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 5 Object Id = 1594878636] </inputbuf>
</process>
</process-list>
<resource-list>
<pagelock fileid="1" pageid="24768207" dbid="5" subresource="FULL" objectname="SectionTable" id="locke19f0d280" mode="SIX" associatedObjectId="72057612168593408">
<owner-list>
<owner id="process10ff03d498" mode="SIX" />
</owner-list>
<waiter-list>
<waiter id="process10f2ea0188" mode="S" requestType="wait" />
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="23196243" dbid="5" subresource="FULL" objectname="SectionTable" id="locke4b2da480" mode="SIX" associatedObjectId="72057612168593408">
<owner-list>
<owner id="process10f2ea0188" mode="SIX" />
</owner-list>
<waiter-list>
<waiter id="process10ff03d498" mode="S" requestType="wait" />
</waiter-list>
</pagelock>
</resource-list>
</deadlock>
This is what the form copying procedure itself looks like (all the inputs, except the first parameter, are the same for the two processes.
For example, process1 = CopyForm (12345, 12, 35), process2 = CopyForm (54321, 12, 35)):
Here is the code itself with the procedures:
CREATE PROCEDURE [dbo].[CopyForm](#FormId as uniqueidentifier, #SrcFormId as uniqueidentifier, #DestFormTypeId as uniqueidentifier)
AS
BEGIN
/* Here we declare the variables */
SET NOCOUNT ON
SET ANSI_WARNINGS OFF
/*code to create a new form */
DECLARE cr CURSOR LOCAL FAST_FORWARD FOR
SELECT ObjectID FROM SectionTable
WHERE Form = #SrcFormId
ORDER BY OrderNum desc
OPEN cr
FETCH NEXT FROM cr INTO #SectionID
WHILE ##FETCH_STATUS = 0 BEGIN
EXEC CopySectionInt #SectionID, #FormId, null, null
FETCH NEXT FROM cr INTO #SectionID
END
CLOSE cr
DEALLOCATE cr
END
GO
CREATE PROCEDURE [dbo].[CopySectionInt](
#SrcSectionId as uniqueidentifier,
#DestFormId as uniqueidentifier,
#PrevSectId as uniqueidentifier,
#SectionId uniqueidentifier )
AS
BEGIN
/* Here we declare the variables */
SET NOCOUNT ON
IF #SectionId IS NULL SELECT #SectionId = newid()
IF #PrevSectId IS NULL
SET #nSectionNumber = 1
ELSE
SELECT #nSectionNumber = OrderNum + 1 FROM SectionTable WHERE ObjectID = #PrevSectId
/* Here we create a new section */
EXEC CreateSectionTable #SectionId
/* remaining code */
END
GO
CREATE PROCEDURE [dbo].[CreateSectionTable]( #argObjectID uniqueidentifier )
AS
BEGIN
/* Here we declare the variables */
SELECT #nSectionNumber = OrderNum FROM SectionTable WHERE ObjectID = #argObjectID
SELECT #nTableIndex = Max(DataTableIndex) + 1 FROM SectionTable
SET #nTableIndex = ISNULL( #nTableIndex, 1 )
UPDATE SectionTable SET DataTableIndex = #nTableIndex, OrderNum = #nSectionNumber WHERE ObjectID = #argObjectID
END
GO
I don't understand how these two processes are blocking each other if they are both accessing the same resource? And how can I fix this error?
Would blocking the CopyForm procedure with sp_getapplock help me in this case ? Or is there a way to solve the problem without blocking?

Page level Deadlock on same delete query

In SQL Server I am issuing the following query:
DELETE FROM TableA WHERE tableB_id IN (SELECT ID from TableB WHERE FileID = #P0)
The query is being called in parallel by multiple processes and which is causing a page-level deadlock issue.
I also have NONCLUSTERED INDEX defined on tableB_id column of TableA which is FK as well.
I am also sharing deadlock XML below. Can anyone help me how can I prevent this deadlock?
<deadlock>
<victim-list>
<victimProcess id="process1a0de90e108" />
</victim-list>
<process-list>
<process id="process1a0de90e108" taskpriority="0" logused="2436" waitresource="PAGE: 6:1:17997419 " waittime="4726" ownerId="3967991339" transactionname="implicit_transaction" lasttranstarted="2021-06-07T21:18:08.423" XDES="0x19fa9470428" lockMode="U" schedulerid="2" kpid="7264" status="suspended" spid="2460" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2021-06-07T21:18:08.777" lastbatchcompleted="2021-06-07T21:18:08.777" lastattention="1900-01-01T00:00:00.777" clientapp="Microsoft JDBC Driver for SQL Server" hostname="test_app-7c98f79f44-mz8jf" hostpid="0" loginname="test_user" isolationlevel="read committed (2)" xactid="3967991339" currentdb="6" currentdbname="p01-ardb" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
<executionStack>
<frame procname="unknown" queryhash="0x9453568569bd0807" queryplanhash="0x1d037286349af98c" line="1" stmtstart="24" stmtend="178" sqlhandle="0x0200000098b1eb2a734675ebd923e42ae1e8765c543d5e020000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(#P0 bigint)DELETE FROM TableA WHERE tableB_id IN (SELECT ID from TableB WHERE FileID = #P0) </inputbuf>
</process>
<process id="process1a0f2886108" taskpriority="0" logused="117716" waitresource="PAGE: 6:1:17915872 " waittime="4747" ownerId="3967991523" transactionname="implicit_transaction" lasttranstarted="2021-06-07T21:18:08.470" XDES="0x1a015ef8428" lockMode="U" schedulerid="4" kpid="51220" status="suspended" spid="2425" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2021-06-07T21:18:08.853" lastbatchcompleted="2021-06-07T21:18:08.853" lastattention="1900-01-01T00:00:00.853" clientapp="Microsoft JDBC Driver for SQL Server" hostname="test_app-7c98f79f44-mz8jf" hostpid="0" loginname="test_user" isolationlevel="read committed (2)" xactid="3967991523" currentdb="6" currentdbname="p01-ardb" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
<executionStack>
<frame procname="unknown" queryhash="0x9453568569bd0807" queryplanhash="0x1d037286349af98c" line="1" stmtstart="24" stmtend="178" sqlhandle="0x0200000098b1eb2a734675ebd923e42ae1e8765c543d5e020000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(#P0 bigint)DELETE FROM TableA WHERE tableB_id IN (SELECT ID from TableB WHERE FileID = #P0) </inputbuf>
</process>
</process-list>
<resource-list>
<pagelock fileid="1" pageid="17997419" dbid="6" subresource="FULL" objectname="f8e7ffa7-ac56-4e56-8ca2-70672c9fe337.AR.TableA" id="lock19e62889280" mode="UIX" associatedObjectId="72057594635354112">
<owner-list>
<owner id="process1a0f2886108" mode="UIX" />
</owner-list>
<waiter-list>
<waiter id="process1a0de90e108" mode="U" requestType="wait" />
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="17915872" dbid="6" subresource="FULL" objectname="f8e7ffa7-ac56-4e56-8ca2-70672c9fe337.AR.TableA" id="lock19da5da9780" mode="U" associatedObjectId="72057594635354112">
<owner-list>
<owner id="process1a0de90e108" mode="U" />
</owner-list>
<waiter-list>
<waiter id="process1a0f2886108" mode="U" requestType="wait" />
</waiter-list>
</pagelock>
</resource-list>
</deadlock>
Index definition as follows:
Table B
index_name, index_description, index_keys
CIX_TableB clustered, unique located on datePartitionScheme , TestDate(-)
IX01_TableB nonclustered located on datePartitionScheme FileID
PK_TableB nonclustered, unique, primary key located on PRIMARY ID
Table A
index_name, index_description, index_keys
IX01_TableA nonclustered located on PRIMARY tableB_id
PK_TableA clustered, unique, primary key located on PRIMARY ID
Table definition
CREATE TABLE TableA(
[ID] [int] IDENTITY(1,1) NOT NULL,
[tableB_id ] [bigint] NOT NULL,
CONSTRAINT [PK_TableA] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE TableB WITH CHECK ADD CONSTRAINT [FK_01] FOREIGN KEY([tableB_id])
REFERENCES [AR].TableB ([ID])
CREATE TABLE [TableB](
[FileID] [int] NOT NULL,
[BookgDt] [date] NOT NULL,
[ID] [bigint] NOT NULL,
[Description] [varchar](4000) NULL,
CONSTRAINT [PK_TableB] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
)
GO
ALTER TABLE [TableB] ADD CONSTRAINT [DF_01] DEFAULT (NEXT VALUE FOR [Sequence_01]) FOR [ID]
GO

Understanding Deadlock graph of sql server

I need some little help to understand why a specific deadlock is happening on a specific table of my database. I know a very little of deadlocks, specially deadlocks on a same table.
Could you give some help with this deadlock? I'm not searching a specific solution, I just only want to know why this deadlock is happening:
<deadlock-list>
<deadlock victim="process4aa5b88">
<process-list>
<process id="process4aa5b88" taskpriority="0" logused="0" waitresource="PAGE: 14:1:6535"
waittime="4912" ownerId="260658" transactionname="UPDATE" lasttranstarted="2015-02-10T09:35:10.040"
XDES="0x8006bb70" lockMode="U" schedulerid="8" kpid="2804" status="suspended" spid="221" sbid="0" ecid="5"
priority="0" trancount="0" lastbatchstarted="2015-02-10T09:35:09.993"
lastbatchcompleted="2015-02-10T09:35:09.993" clientapp=".Net SqlClient Data Provider" hostname="ANP-APP"
hostpid="6728" isolationlevel="read committed (2)" xactid="260658" currentdb="14" lockTimeout="4294967295"
clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="2" sqlhandle="0x02000000c7f3e035aa74a68d308785ac6386d1ee4b1f924e">
UPDATE ic_seguimiento_contenedor SET nave_id = M.id_interno, nave_nombre=M.campo2 FROM mantenedor_general M WHERE ic_seguimiento_contenedor.nave_id = 0 AND ic_seguimiento_contenedor.estado_cod<20 AND M.id_empresa=ic_seguimiento_contenedor.id_empresa AND ic_seguimiento_contenedor.id_empresa=105 AND M.mantenedor=&apos;mant_nave&apos; AND ltrim(rtrim(M.campo1))=ltrim(rtrim(ic_seguimiento_contenedor.nave_cod)) AND ic_seguimiento_contenedor.key_negocio =&apos;53E010566725403&apos; </frame>
</executionStack>
<inputbuf> </inputbuf>
</process>
<process id="process4a8b288" taskpriority="0" logused="0" waitresource="PAGE: 14:1:6535"
waittime="6287" ownerId="260658" transactionname="UPDATE" lasttranstarted="2015-02-10T09:35:10.040"
XDES="0xbf9597b0" lockMode="U" schedulerid="7" kpid="6952" status="suspended" spid="221" sbid="0" ecid="7"
priority="0" trancount="0" lastbatchstarted="2015-02-10T09:35:09.993"
lastbatchcompleted="2015-02-10T09:35:09.993" clientapp=".Net SqlClient Data Provider" hostname="ANP-APP"
hostpid="6728" isolationlevel="read committed (2)" xactid="260658" currentdb="14" lockTimeout="4294967295"
clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="2" sqlhandle="0x02000000c7f3e035aa74a68d308785ac6386d1ee4b1f924e">
UPDATE ic_seguimiento_contenedor SET nave_id = M.id_interno, nave_nombre=M.campo2 FROM mantenedor_general M WHERE ic_seguimiento_contenedor.nave_id = 0 AND ic_seguimiento_contenedor.estado_cod<20 AND M.id_empresa=ic_seguimiento_contenedor.id_empresa AND ic_seguimiento_contenedor.id_empresa=105 AND M.mantenedor=&apos;mant_nave&apos; AND ltrim(rtrim(M.campo1))=ltrim(rtrim(ic_seguimiento_contenedor.nave_cod)) AND ic_seguimiento_contenedor.key_negocio =&apos;53E010566725403&apos; </frame>
</executionStack>
<inputbuf> </inputbuf>
</process>
<process id="process463d948" taskpriority="0" logused="0" waitresource="PAGE: 14:1:6503"
waittime="4912" ownerId="260657" transactionname="UPDATE" lasttranstarted="2015-02-10T09:35:10.040"
XDES="0xb4595850" lockMode="U" schedulerid="4" kpid="2060" status="suspended" spid="219" sbid="0" ecid="3"
priority="0" trancount="0" lastbatchstarted="2015-02-10T09:35:09.993"
lastbatchcompleted="2015-02-10T09:35:09.993" clientapp=".Net SqlClient Data Provider" hostname="ANP-APP"
hostpid="6728" isolationlevel="read committed (2)" xactid="260657" currentdb="14" lockTimeout="4294967295"
clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="2" sqlhandle="0x02000000c7f3e035aa74a68d308785ac6386d1ee4b1f924e">
UPDATE ic_seguimiento_contenedor SET nave_id = M.id_interno, nave_nombre=M.campo2 FROM mantenedor_general M WHERE ic_seguimiento_contenedor.nave_id = 0 AND ic_seguimiento_contenedor.estado_cod<20 AND M.id_empresa=ic_seguimiento_contenedor.id_empresa AND ic_seguimiento_contenedor.id_empresa=105 AND M.mantenedor=&apos;mant_nave&apos; AND ltrim(rtrim(M.campo1))=ltrim(rtrim(ic_seguimiento_contenedor.nave_cod)) AND ic_seguimiento_contenedor.key_negocio =&apos;53E010566725403&apos; </frame>
</executionStack>
<inputbuf> </inputbuf>
</process>
<process id="process449ebc8" taskpriority="0" logused="0" waitresource="PAGE: 14:1:6503"
waittime="6287" ownerId="260657" transactionname="UPDATE" lasttranstarted="2015-02-10T09:35:10.040"
XDES="0x80007a70" lockMode="U" schedulerid="1" kpid="6936" status="suspended" spid="219" sbid="0" ecid="5"
priority="0" trancount="0" lastbatchstarted="2015-02-10T09:35:09.993"
lastbatchcompleted="2015-02-10T09:35:09.993" clientapp=".Net SqlClient Data Provider" hostname="ANP-APP"
hostpid="6728" isolationlevel="read committed (2)" xactid="260657" currentdb="14" lockTimeout="4294967295"
clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="2" sqlhandle="0x02000000c7f3e035aa74a68d308785ac6386d1ee4b1f924e">
UPDATE ic_seguimiento_contenedor SET nave_id = M.id_interno, nave_nombre=M.campo2 FROM mantenedor_general M WHERE ic_seguimiento_contenedor.nave_id = 0 AND ic_seguimiento_contenedor.estado_cod<20 AND M.id_empresa=ic_seguimiento_contenedor.id_empresa AND ic_seguimiento_contenedor.id_empresa=105 AND M.mantenedor=&apos;mant_nave&apos; AND ltrim(rtrim(M.campo1))=ltrim(rtrim(ic_seguimiento_contenedor.nave_cod)) AND ic_seguimiento_contenedor.key_negocio =&apos;53E010566725403&apos; </frame>
</executionStack>
<inputbuf> </inputbuf>
</process>
<process id="process4a8b048" taskpriority="0" logused="10000" waittime="4905" schedulerid="7" kpid="6324"
status="suspended" spid="219" sbid="0" ecid="0" priority="0" trancount="2"
lastbatchstarted="2015-02-10T09:35:09.993" lastbatchcompleted="2015-02-10T09:35:09.993"
clientapp=".Net SqlClient Data Provider" hostname="ANP-APP" hostpid="6728" loginname="sa"
isolationlevel="read committed (2)" xactid="260657" currentdb="14" lockTimeout="4294967295"
clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="2" sqlhandle="0x02000000c7f3e035aa74a68d308785ac6386d1ee4b1f924e">
UPDATE ic_seguimiento_contenedor SET nave_id = M.id_interno, nave_nombre=M.campo2 FROM mantenedor_general M WHERE ic_seguimiento_contenedor.nave_id = 0 AND ic_seguimiento_contenedor.estado_cod<20 AND M.id_empresa=ic_seguimiento_contenedor.id_empresa AND ic_seguimiento_contenedor.id_empresa=105 AND M.mantenedor=&apos;mant_nave&apos; AND ltrim(rtrim(M.campo1))=ltrim(rtrim(ic_seguimiento_contenedor.nave_cod)) AND ic_seguimiento_contenedor.key_negocio =&apos;53E010566725403&apos; </frame>
</executionStack>
<inputbuf> UPDATE ic_seguimiento_contenedor SET nave_id = M.id_interno, nave_nombre=M.campo2 FROM mantenedor_general M WHERE ic_seguimiento_contenedor.nave_id = 0 AND ic_seguimiento_contenedor.estado_cod<20 AND M.id_empresa=ic_seguimiento_contenedor.id_empresa AND ic_seguimiento_contenedor.id_empresa=105 AND M.mantenedor=&apos;mant_nave&apos; AND ltrim(rtrim(M.campo1))=ltrim(rtrim(ic_seguimiento_contenedor.nave_cod)) AND ic_seguimiento_contenedor.key_negocio =&apos;53E010566725403&apos; </inputbuf>
</process>
</process-list>
<resource-list>
<pagelock fileid="1" pageid="6535" dbid="14" objectname="icomexvi_dys.dbo.ic_seguimiento_contenedor" id="lock95e1e800" mode="U" associatedObjectId="72057594108248064">
<owner-list/>
<waiter-list>
<waiter id="process4aa5b88" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="6535" dbid="14" objectname="icomexvi_dys.dbo.ic_seguimiento_contenedor" id="lock95e1e800" mode="U" associatedObjectId="72057594108248064">
<owner-list>
<owner id="process4a8b048" mode="U"/>
</owner-list>
<waiter-list>
<waiter id="process4a8b288" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="6503" dbid="14" objectname="icomexvi_dys.dbo.ic_seguimiento_contenedor" id="lock96c23080" mode="U" associatedObjectId="72057594108248064">
<owner-list/>
<waiter-list>
<waiter id="process463d948" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="6503" dbid="14" objectname="icomexvi_dys.dbo.ic_seguimiento_contenedor" id="lock96c23080" mode="U" associatedObjectId="72057594108248064">
<owner-list>
<owner id="process4aa5b88" mode="U"/>
</owner-list>
<waiter-list>
<waiter id="process449ebc8" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<exchangeEvent id="Pipec6a2eac0" WaitType="e_waitPipeGetRow" nodeId="4">
<owner-list>
<owner id="process463d948"/>
</owner-list>
<waiter-list>
<waiter id="process4a8b048"/>
</waiter-list>
</exchangeEvent>
</resource-list>
</deadlock>
</deadlock-list>
I very appreciate your help!
Thanks in advance
These are the processes: process4aa5b88, process4a8b288, process463d948, process449ebc8 and process4a8b048.
Page 6535 is owned by process4a8b048 and waited by process4aa5b88 and process4a8b288.
Page 6503 is owned by process4aa5b88 and waited by process449ebc8 and process463d948.
Parallel exchange pipe Pipec6a2eac0 is owned by process463d948 and waited by process4a8b048.
The deadlock cycle is this:
process4aa5b88 waits page 6535, owned by process4a8b048
process4a8b048 waits exchange pipe owned by process463d948
process463d948 waits page 6503 owned by process4aa5b88
QED a cycle in the wait list => deadlock
Presence of parallelism and page granularity locks during scan is a clear indication of a missing index. Review the WHERE clause, make sure you have SARGable arguments. Read Index Design Basics and all linked chapters.
This does not answer your question but if you want to become aware of deadlocks in real-time then you can create an alert that calls a sp that sends an email to sql operators. It pretty straightforward.
Create a table to hold deadlock events.
CREATE TABLE [dbo].[DeadlockEvents](
[AlertTime] [datetime] NULL,
[DeadlockGraph] [xml] NULL
) ON [PRIMARY]
Create a SQL Agent Job with the following exec sql as step 1.
DECLARE #xml XML;
SELECT #xml=N'$(ESCAPE_SQUOTE(WMI(TextData)))'
INSERT INTO ILMDW.dbo.DeadlockEvents
(AlertTime, DeadlockGraph)
VALUES (getdate(), N'$(ESCAPE_SQUOTE(WMI(TextData)))')
EXEC ILMDW.dbo.MAINTENANCE_Deadlock_Graph #xml
Create a SQL Server Management/Alert configured as follows.
Then have the sp send emails to you or othere when a deadlock occurs -->
ALTER PROC [dbo].[MAINTENANCE_Deadlock_Graph] #xml XML
AS
BEGIN
SET NOCOUNT ON;
DECLARE #body VARCHAR(MAX)
CREATE TABLE #victim_list(process_id VARCHAR(100))
CREATE TABLE #processdetails
(
id VARCHAR(100),
taskpriority VARCHAR(100),
logused VARCHAR(100),
waitresource VARCHAR(100),
waittime VARCHAR(100),
ownerId VARCHAR(100),
transactionname VARCHAR(100),
lasttranstarted VARCHAR(100),
XDES VARCHAR(100),
lockMode VARCHAR(100),
schedulerid VARCHAR(100),
kpid VARCHAR(100),
status VARCHAR(100),
spid VARCHAR(100),
sbid VARCHAR(100),
ecid VARCHAR(100),
priority VARCHAR(100),
trancount VARCHAR(100),
lastbatchstarted VARCHAR(100),
lastbatchcompleted VARCHAR(100),
clientapp VARCHAR(100),
hostname VARCHAR(100),
hostpid VARCHAR(100),
loginname VARCHAR(100),
isolationlevel VARCHAR(100),
xactid VARCHAR(100),
currentdb VARCHAR(100),
lockTimeout VARCHAR(100),
clientoption1 VARCHAR(100),
clientoption2 VARCHAR(100)
)
CREATE TABLE #frame_details
(
id VARCHAR(100),
procname VARCHAR(100),
line VARCHAR(100),
stmtstart VARCHAR(100),
sqlhandle VARCHAR(100)
)
CREATE TABLE #frame_values
(
id VARCHAR(100),
frame VARCHAR(max)
)
CREATE TABLE #input_buffer
(
id VARCHAR(100),
inputbuf VARCHAR(max)
)
CREATE TABLE #resource_details_keylock
(
hobtid VARCHAR(100),
dbid VARCHAR(100),
objectname VARCHAR(100),
indexname VARCHAR(100),
lock_id VARCHAR(100),
mode VARCHAR(100),
associatedObjectId VARCHAR(100),
owner_id VARCHAR(100),
owner_mode VARCHAR(100),
waiter_id VARCHAR(100),
waiter_mode VARCHAR(100),
waiter_requestType VARCHAR(100)
)
CREATE TABLE #resource_details_objectlock
(
lockpartition VARCHAR(100),
objid VARCHAR(100),
subresource VARCHAR(100),
dbid VARCHAR(100),
objectname VARCHAR(100),
lock_id VARCHAR(100),
mode VARCHAR(100),
associatedObjectId VARCHAR(100),
owner_id VARCHAR(100),
owner_mode VARCHAR(100),
waiter_id VARCHAR(100),
waiter_mode VARCHAR(100),
waiter_requestType VARCHAR(100)
)
CREATE TABLE #resource_details_databaselock
(
subresource VARCHAR(100),
dbid VARCHAR(100),
dbname VARCHAR(100),
lock_id VARCHAR(100),
mode VARCHAR(100),
owner_id VARCHAR(100),
owner_mode VARCHAR(100),
waiter_id VARCHAR(100),
waiter_mode VARCHAR(100),
waiter_requestType VARCHAR(100)
)
CREATE TABLE #resource_details_exchangeEvent
(
id VARCHAR(100),
waitType VARCHAR(100),
nodeId VARCHAR(100),
owner_id VARCHAR(100),
owner_mode VARCHAR(100),
waiter_id VARCHAR(100),
waiter_mode VARCHAR(100),
waiter_requestType VARCHAR(100)
)
CREATE TABLE #resource_details_metadatalock
(
subresource VARCHAR(100),
classid VARCHAR(100),
dbid VARCHAR(100),
dbname VARCHAR(100),
lock_id VARCHAR(100),
mode VARCHAR(100),
owner_id VARCHAR(100),
owner_mode VARCHAR(100),
waiter_id VARCHAR(100),
waiter_mode VARCHAR(100),
waiter_requestType VARCHAR(100)
)
CREATE TABLE #resource_details_pagelock
(
fileid VARCHAR(100),
pageid VARCHAR(100),
dbid VARCHAR(100),
dbname VARCHAR(100),
objectname VARCHAR(100),
lock_id VARCHAR(100),
mode VARCHAR(100),
associatedObjectId VARCHAR(100),
owner_id VARCHAR(100),
owner_mode VARCHAR(100),
waiter_id VARCHAR(100),
waiter_mode VARCHAR(100),
waiter_requestType VARCHAR(100)
)
create table #resource_details_ridlock
(
pageid VARCHAR(100),
dbid VARCHAR(100),
dbname VARCHAR(100),
objectname VARCHAR(100),
lock_id VARCHAR(100),
mode VARCHAR(100),
associatedObjectId VARCHAR(100),
owner_id VARCHAR(100),
owner_mode VARCHAR(100),
waiter_id VARCHAR(100),
waiter_mode VARCHAR(100),
waiter_requestType VARCHAR(100)
)
INSERT INTO #victim_list
SELECT dl.n.value('#victim','VARCHAR(100)')
FROM #xml.nodes('TextData/deadlock-list/deadlock') dl(n)
INSERT INTO #processdetails
select dl.n.value('#id1','VARCHAR(100)') AS id,
dl.n.value('#taskpriority1','VARCHAR(100)') AS taskpriority,
dl.n.value('#logused1','VARCHAR(100)') AS logused,
dl.n.value('#waitresource1','VARCHAR(100)') AS waitresource,
dl.n.value('#waittime1','VARCHAR(100)') AS waittime,
dl.n.value('#ownerId1','VARCHAR(100)') AS ownerId,
dl.n.value('#transactionname1','VARCHAR(100)') AS transactionname,
dl.n.value('#lasttranstarted1','VARCHAR(100)') AS lasttranstarted,
dl.n.value('#XDES1','VARCHAR(100)') AS XDES,
dl.n.value('#lockMode1','VARCHAR(100)') AS lockMode,
dl.n.value('#schedulerid1','VARCHAR(100)') AS schedulerid,
dl.n.value('#kpid1','VARCHAR(100)') AS kpid,
dl.n.value('#status1','VARCHAR(100)') AS status,
dl.n.value('#spid1','VARCHAR(100)') AS spid,
dl.n.value('#sbid1','VARCHAR(100)') AS sbid,
dl.n.value('#ecid1','VARCHAR(100)') AS ecid,
dl.n.value('#priority1','VARCHAR(100)') AS priority,
dl.n.value('#trancount1','VARCHAR(100)') AS trancount,
dl.n.value('#lastbatchstarted1','VARCHAR(100)') AS lastbatchstarted,
dl.n.value('#lastbatchcompleted1','VARCHAR(100)') AS lastbatchcompleted,
dl.n.value('#clientapp1','VARCHAR(100)') AS clientapp,
dl.n.value('#hostname1','VARCHAR(100)') AS hostname,
dl.n.value('#hostpid1','VARCHAR(100)') AS hostpid,
dl.n.value('#loginname1','VARCHAR(100)') AS loginname,
dl.n.value('#isolationlevel1','VARCHAR(100)') AS isolationlevel,
dl.n.value('#xactid1','VARCHAR(100)') AS xactid,
dl.n.value('#currentdb1','VARCHAR(100)') AS currentdb,
dl.n.value('#lockTimeout1','VARCHAR(100)') AS lockTimeout,
dl.n.value('#clientoption11','VARCHAR(100)') AS clientoption1,
dl.n.value('#clientoption21','VARCHAR(100)') AS clientoption2
FROM #xml.nodes('//TextData/deadlock-list/deadlock/process-list/process') dl(n)
INSERT INTO #frame_details
SELECT dl.n.value('../../#id1','VARCHAR(100)') AS id,
dl.n.value('#procname1','VARCHAR(100)') AS procname,
dl.n.value('#line1','VARCHAR(100)') AS line,
dl.n.value('#stmtstart1','VARCHAR(100)') AS stmtstart,
dl.n.value('#sqlhandle1','VARCHAR(100)') AS sqlhandle
FROM #xml.nodes('//TextData/deadlock-list/deadlock/process-list/process/executionStack/frame') dl(n)
INSERT INTO #frame_values
SELECT dl.n.value('../#id1','VARCHAR(100)') AS id,
dl.n.value('frame1','VARCHAR(100)') AS frame
FROM #xml.nodes('//TextData/deadlock-list/deadlock/process-list/process/executionStack') dl(n)
INSERT INTO #input_buffer
SELECT dl.n.value('#id1','VARCHAR(100)') AS id,
dl.n.value('inputbuf1','VARCHAR(100)') AS inputbuf
FROM #xml.nodes('//TextData/deadlock-list/deadlock/process-list/process') dl(n)
INSERT INTO #resource_details_keylock
SELECT dl.n.value('#hobtid1','VARCHAR(100)') AS hobtid,
dl.n.value('#dbid1','VARCHAR(100)') AS dbid,
dl.n.value('#objectname1','VARCHAR(100)') AS objectname,
dl.n.value('#indexname1','VARCHAR(100)') AS indexname,
dl.n.value('#id1','VARCHAR(100)') AS lock_id,
dl.n.value('#mode1','VARCHAR(100)') AS mode,
dl.n.value('#associatedObjectId1','VARCHAR(100)') AS associatedObjectId,
dl.n.value('(owner-list/owner)1/#id','VARCHAR(100)') AS owner_id,
dl.n.value('(owner-list/owner)1/#mode','VARCHAR(100)') AS owner_mode,
dl.n.value('(waiter-list/waiter)1/#id','VARCHAR(100)') AS waiter_id,
dl.n.value('(waiter-list/waiter)1/#mode','VARCHAR(100)') AS waiter_mode,
dl.n.value('(waiter-list/waiter)1/#requestType','VARCHAR(100)') AS waiter_requestType
FROM #xml.nodes('//TextData/deadlock-list/deadlock/resource-list/keylock') dl(n)
INSERT INTO #resource_details_objectlock
SELECT dl.n.value('#lockpartition1','VARCHAR(100)') AS lockpartition,
dl.n.value('#objid1','VARCHAR(100)') AS objid,
dl.n.value('#subresource1','VARCHAR(100)') AS subresource,
dl.n.value('#dbid1','VARCHAR(100)') AS dbid,
dl.n.value('#objectname1','VARCHAR(100)') AS objectname,
dl.n.value('#id1','VARCHAR(100)') AS lock_id,
dl.n.value('#mode1','VARCHAR(100)') AS mode,
dl.n.value('#associatedObjectId1','VARCHAR(100)') AS associatedObjectId,
dl.n.value('(owner-list/owner)1/#id','VARCHAR(100)') AS owner_id,
dl.n.value('(owner-list/owner)1/#mode','VARCHAR(100)') AS owner_mode,
dl.n.value('(waiter-list/waiter)1/#id','VARCHAR(100)') AS waiter_id,
dl.n.value('(waiter-list/waiter)1/#mode','VARCHAR(100)') AS waiter_mode,
dl.n.value('(waiter-list/waiter)1/#requestType','VARCHAR(100)') AS waiter_requestType
FROM #xml.nodes('//TextData/deadlock-list/deadlock/resource-list/objectlock') dl(n)
INSERT INTO #resource_details_databaselock
SELECT dl.n.value('#subresource1','VARCHAR(100)') AS subresource,
dl.n.value('#dbid1','VARCHAR(100)') AS dbid,
db_name(dl.n.value('#dbid1','VARCHAR(100)')) AS dbname,
dl.n.value('#id1','VARCHAR(100)') AS lock_id,
dl.n.value('#mode1','VARCHAR(100)') AS mode,
dl.n.value('(owner-list/owner)1/#id','VARCHAR(100)') AS owner_id,
dl.n.value('(owner-list/owner)1/#mode','VARCHAR(100)') AS owner_mode,
dl.n.value('(waiter-list/waiter)1/#id','VARCHAR(100)') AS waiter_id,
dl.n.value('(waiter-list/waiter)1/#mode','VARCHAR(100)') AS waiter_mode,
dl.n.value('(waiter-list/waiter)1/#requestType','VARCHAR(100)') AS waiter_requestType
FROM #xml.nodes('//TextData/deadlock-list/deadlock/resource-list/databaselock') dl(n)
INSERT INTO #resource_details_exchangeEvent
SELECT dl.n.value('#id1','VARCHAR(100)') AS lock_id,
dl.n.value('#waitType1','VARCHAR(100)') AS waitType,
dl.n.value('#nodeId1','VARCHAR(100)') AS nodeId,
dl.n.value('(owner-list/owner)1/#id','VARCHAR(100)') AS owner_id,
dl.n.value('(owner-list/owner)1/#mode','VARCHAR(100)') AS owner_mode,
dl.n.value('(waiter-list/waiter)1/#id','VARCHAR(100)') AS waiter_id,
dl.n.value('(waiter-list/waiter)1/#mode','VARCHAR(100)') AS waiter_mode,
dl.n.value('(waiter-list/waiter)1/#requestType','VARCHAR(100)') AS waiter_requestType
FROM #xml.nodes('//TextData/deadlock-list/deadlock/resource-list/exchangeEvent') dl(n)
INSERT INTO #resource_details_metadatalock
SELECT dl.n.value('#subresource1','VARCHAR(100)') AS subresource,
dl.n.value('#classid1','VARCHAR(100)') AS classid,
dl.n.value('#dbid1','VARCHAR(100)') AS dbid,
db_name(dl.n.value('#dbid1','VARCHAR(100)')) AS dbname,
dl.n.value('#id1','VARCHAR(100)') AS lock_id,
dl.n.value('#mode1','VARCHAR(100)') AS mode,
dl.n.value('(owner-list/owner)1/#id','VARCHAR(100)') AS owner_id,
dl.n.value('(owner-list/owner)1/#mode','VARCHAR(100)') AS owner_mode,
dl.n.value('(waiter-list/waiter)1/#id','VARCHAR(100)') AS waiter_id,
dl.n.value('(waiter-list/waiter)1/#mode','VARCHAR(100)') AS waiter_mode,
dl.n.value('(waiter-list/waiter)1/#requestType','VARCHAR(100)') AS waiter_requestType
FROM #xml.nodes('//TextData/deadlock-list/deadlock/resource-list/metadatalock') dl(n)
INSERT INTO #resource_details_pagelock
SELECT dl.n.value('#fileid1','VARCHAR(100)') AS fileid,
dl.n.value('#pageid1','VARCHAR(100)') AS pageid,
dl.n.value('#dbid1','VARCHAR(100)') AS dbid,
db_name(dl.n.value('#dbid1','VARCHAR(100)')) AS dbname,
dl.n.value('#objectname1','VARCHAR(100)') AS objectname,
dl.n.value('#id1','VARCHAR(100)') AS lock_id,
dl.n.value('#mode1','VARCHAR(100)') AS mode,
dl.n.value('#associatedObjectId1','VARCHAR(100)') AS associatedObjectId,
dl.n.value('(owner-list/owner)1/#id','VARCHAR(100)') AS owner_id,
dl.n.value('(owner-list/owner)1/#mode','VARCHAR(100)') AS owner_mode,
dl.n.value('(waiter-list/waiter)1/#id','VARCHAR(100)') AS waiter_id,
dl.n.value('(waiter-list/waiter)1/#mode','VARCHAR(100)') AS waiter_mode,
dl.n.value('(waiter-list/waiter)1/#requestType','VARCHAR(100)') AS waiter_requestType
FROM #xml.nodes('//TextData/deadlock-list/deadlock/resource-list/pagelock') dl(n)
INSERT INTO #resource_details_ridlock
SELECT dl.n.value('#pageid1','VARCHAR(100)') AS pageid,
dl.n.value('#dbid1','VARCHAR(100)') AS dbid,
db_name(dl.n.value('#dbid1','VARCHAR(100)')) AS dbname,
dl.n.value('#objectname1','VARCHAR(100)') AS objectname,
dl.n.value('#id1','VARCHAR(100)') AS lock_id,
dl.n.value('#mode1','VARCHAR(100)') AS mode,
dl.n.value('#associatedObjectId1','VARCHAR(100)') AS associatedObjectId,
dl.n.value('(owner-list/owner)1/#id','VARCHAR(100)') AS owner_id,
dl.n.value('(owner-list/owner)1/#mode','VARCHAR(100)') AS owner_mode,
dl.n.value('(waiter-list/waiter)1/#id','VARCHAR(100)') AS waiter_id,
dl.n.value('(waiter-list/waiter)1/#mode','VARCHAR(100)') AS waiter_mode,
dl.n.value('(waiter-list/waiter)1/#requestType','VARCHAR(100)') AS waiter_requestType
FROM #xml.nodes('//TextData/deadlock-list/deadlock/resource-list/ridlock') dl(n)
SELECT #body='Process id(Victim)'
SELECT #body=#body+''+isnull(process_id,'')+'' from #victim_list
SELECT #body=#body+''
SELECT #body=#body+'Process Details:
Process id
DB_Name
procname
waittime
lockMode
trancount
clientapp
hostname
loginname
frame
inputbuf
'
SELECT DISTINCT isnull(pd.id,'') as [id],
isnull(db_name(pd.currentdb),'') as [currentdb],
isnull(fd.procname,'') as [procname],
isnull(pd.waittime,'') as [waittime],
isnull(pd.lockMode,'') as [lockMode],
isnull(pd.trancount,'') as [trancount],
isnull(pd.clientapp,'') as [clientapp],
isnull(pd.hostname,'') as [hostname],
isnull(pd.loginname,'') as [loginname],
isnull(fv.frame,'') as [frame],
isnull(ib.inputbuf,'') as [inputbuf]
into #p_details_temp
from #processdetails pd
left join #frame_details fd on pd.id=fd.id
left join #frame_values fv on fd.id=fv.id
left join #input_buffer ib on fv.id=ib.id
SELECT #body=#body+
''+id+''+
''+currentdb+''+
''+procname+''+
''+waittime+''+
''+lockMode+''+
''+trancount+''+
''+clientapp+''+
''+hostname+''+
''+loginname+''+
''+frame+''+
''+inputbuf+''
FROM #p_details_temp
SELECT #body=#body+''
IF EXISTS (SELECT TOP 1 * FROM #resource_details_keylock)
BEGIN
SELECT #body=#body+'Keylock: '+
'hobtid,'+
'dbid,'+
'objectname,'+
'indexname,'+
'lock_id,'+
'mode,'+
'associatedObjectId,'+
'owner_id,'+
'owner_mode,'+
'waiter_id,'+
'waiter_mode,'+
'waiter_requestType,'+
''
select #body=#body+''+
''+isnull(hobtid,'')+''+
''+isnull(dbid,'')+''+
''+isnull(objectname,'')+''+
''+isnull(indexname,'')+''+
''+isnull(lock_id,'')+''+
''+isnull(mode,'')+''+
''+isnull(associatedObjectId,'')+''+
''+isnull(owner_id,'')+''+
''+isnull(owner_mode,'')+''+
''+isnull(waiter_id,'')+''+
''+isnull(waiter_mode,'')+''+
''+isnull(waiter_requestType,'')+''+
''
from #resource_details_keylock
select #body=#body+''
END
IF EXISTS (SELECT TOP 1 * FROM #resource_details_objectlock)
BEGIN
SELECT #body=#body+'ObjectLock: '+
'lockpartition,'+
'objid,'+
'subresource,'+
'dbid,'+
'objectname,'+
'lock_id,'+
'mode,'+
'associatedObjectId,'+
'owner_id,'+
'owner_mode,'+
'waiter_id,'+
'waiter_mode,'+
'waiter_requestType,'+
''
SELECT #body=#body+''+
''+isnull(lockpartition,'')+''+
''+isnull(objid,'')+''+
''+isnull(subresource,'')+''+
''+isnull(dbid,'')+''+
''+isnull(objectname,'')+''+
''+isnull(lock_id,'')+''+
''+isnull(mode,'')+''+
''+isnull(associatedObjectId,'')+''+
''+isnull(owner_id,'')+''+
''+isnull(owner_mode,'')+''+
''+isnull(waiter_id,'')+''+
''+isnull(waiter_mode,'')+''+
''+isnull(waiter_requestType,'')+''+
''
FROM #resource_details_objectlock
SELECT #body=#body+''
END
IF EXISTS (SELECT TOP 1 * FROM #resource_details_databaselock)
BEGIN
SELECT #body=#body+'DatabaseLock:<br><table border="1"> <tr>'+
'<th>subresource,</th>'+
'<th>dbid,</th>'+
'<th>dbname,</th>'+
'<th>lock_id,</th>'+
'<th>mode,</th>'+
'<th>owner_id,</th>'+
'<th>owner_mode,</th>'+
'<th>waiter_id,</th>'+
'<th>waiter_mode,</th>'+
'<th>waiter_requestType,</th>'+
'</tr>'
SELECT #body=#body+'<tr>'+
'<td>'+isnull(subresource,'')+'</td>'+
'<td>'+isnull(dbid,'')+'</td>'+
'<td>'+isnull(dbname,'')+'</td>'+
'<td>'+isnull(lock_id,'')+'</td>'+
'<td>'+isnull(mode,'')+'</td>'+
'<td>'+isnull(owner_id,'')+'</td>'+
'<td>'+isnull(owner_mode,'')+'</td>'+
'<td>'+isnull(waiter_id,'')+'</td>'+
'<td>'+isnull(waiter_mode,'')+'</td>'+
'<td>'+isnull(waiter_requestType,'')+'</td>'+
'</tr>'
from #resource_details_databaselock
select #body=#body+'</table><br/><br/>'
END
IF EXISTS (SELECT TOP 1 * FROM #resource_details_exchangeEvent)
BEGIN
SELECT #body=#body+'ExchangeEvent: '+
'lock_id,'+
'waitType,'+
'nodeId,'+
'owner_id,'+
'owner_mode,'+
'waiter_id,'+
'waiter_mode,'+
'waiter_requestType,'+
''
SELECT #body=#body+''+
''+isnull(id,'')+''+
''+isnull(waitType,'')+''+
''+isnull(nodeId,'')+''+
''+isnull(owner_id,'')+''+
''+isnull(owner_mode,'')+''+
''+isnull(waiter_id,'')+''+
''+isnull(waiter_mode,'')+''+
''+isnull(waiter_requestType,'')+''+
''
FROM #resource_details_exchangeEvent
SELECT #body=#body+''
END
IF EXISTS (SELECT TOP 1 * FROM #resource_details_metadatalock)
BEGIN
SELECT #body=#body+'MetadataLock: '+
'subresource,'+
'classid,'+
'dbid,'+
'dbname,'+
'lock_id,'+
'mode,'+
'owner_id,'+
'owner_mode,'+
'waiter_id,'+
'waiter_mode,'+
'waiter_requestType,'+
''
SELECT #body=#body+''+
''+isnull(subresource,'')+''+
''+isnull(classid,'')+''+
''+isnull(dbid,'')+''+
''+isnull(dbname,'')+''+
''+isnull(lock_id,'')+''+
''+isnull(mode,'')+''+
''+isnull(owner_id,'')+''+
''+isnull(owner_mode,'')+''+
''+isnull(waiter_id,'')+''+
''+isnull(waiter_mode,'')+''+
''+isnull(waiter_requestType,'')+''+
''
FROM #resource_details_metadatalock
SELECT #body=#body+''
END
IF EXISTS (SELECT TOP 1 * FROM #resource_details_pagelock)
BEGIN
SELECT #body=#body+'PageLock: '+
'fileid,'+
'pageid,'+
'dbid,'+
'dbname,'+
'objectname,'+
'lock_id,'+
'mode,'+
'associatedObjectId,'+
'owner_id,'+
'owner_mode,'+
'waiter_id,'+
'waiter_mode,'+
'waiter_requestType,'+
''
SELECT #body=#body+''+
''+isnull(fileid,'')+''+
''+isnull(pageid,'')+''+
''+isnull(dbid,'')+''+
''+isnull(dbname,'')+''+
''+isnull(objectname,'')+''+
''+isnull(lock_id,'')+''+
''+isnull(mode,'')+''+
''+isnull(associatedObjectId,'')+''+
''+isnull(owner_id,'')+''+
''+isnull(owner_mode,'')+''+
''+isnull(waiter_id,'')+''+
''+isnull(waiter_mode,'')+''+
''+isnull(waiter_requestType,'')+''+
''
FROM #resource_details_pagelock
SELECT #body=#body+''
END
IF EXISTS (SELECT TOP 1 * FROM #resource_details_ridlock)
BEGIN
SELECT #body=#body+'RidLock: '+
'pageid,'+
'dbid,'+
'dbname,'+
'objectname,'+
'lock_id,'+
'mode,'+
'associatedObjectId,'+
'owner_id,'+
'owner_mode,'+
'waiter_id,'+
'waiter_mode,'+
'waiter_requestType,'+
''
SELECT #body=#body+''+
''+isnull(pageid,'')+''+
''+isnull(dbid,'')+''+
''+isnull(dbname,'')+''+
''+isnull(objectname,'')+''+
''+isnull(lock_id,'')+''+
''+isnull(mode,'')+''+
''+isnull(associatedObjectId,'')+''+
''+isnull(owner_id,'')+''+
''+isnull(owner_mode,'')+''+
''+isnull(waiter_id,'')+''+
''+isnull(waiter_mode,'')+''+
''+isnull(waiter_requestType,'')+''+
''
FROM #resource_details_ridlock
SELECT #body=#body+''
END
SELECT #body=#body+'Original XML'+
replace( replace( convert(VARCHAR(MAX),#xml), '<','<' ), '>','>' )+
''
DECLARE #email_distribution_list VARCHAR(1024)
SELECT #email_distribution_list = 'ross#ilearn.com;brad#ilearn.com;kenny#ilearn.com;spenser#ilearn.com'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SQL NOTIFICATIONS',
#recipients=#email_distribution_list,
#body = #body,
#body_format='HTML',
#subject = 'Alert! DeadLock Occurred On Server',
#importance = 'High' ;
DROP TABLE #victim_list
DROP TABLE #processdetails
DROP TABLE #frame_details
DROP TABLE #frame_values
DROP TABLE #input_buffer
DROP TABLE #resource_details_databaselock
DROP TABLE #resource_details_exchangeEvent
DROP TABLE #resource_details_keylock
DROP TABLE #resource_details_metadatalock
DROP TABLE #resource_details_objectlock
DROP TABLE #resource_details_pagelock
DROP TABLE #resource_details_ridlock
DROP TABLE #p_details_temp
END

Deadlock puzzle : Victim doesn't own any resource, used to kill to resolve deadlock

I've strange deadlock graph where the victim chosen by MSSQL server 2008 isn't part of the deadlock loop.
This deadlock is between select and insert.
The deadlock resource is a single table where all selects want waitresource = "KEY: 6:72057594098810880 (ffffffffffff)"
Question1 : Does ffffffffffff here mean they want a full range lock on whole table? Or whole key range? Or something else?
We are following a rule where table will never have a row with primary key id = 0.
There are few places where we do this kind of check
select foo from bar where #someId = 0 OR SomeId = #someId.
I also came to know about that SQL doesn't short-circuit the expression. So if I pass #someId = 0 that doesn't guarantee the other part won't be evaluated. So it's possible that SQL can execute at runtime SomeId = #someId.
Question2 : Since it wasn't able to find 0 in SomeId, SQL will acquire a range lock on whole table (or row) so no one else inserts 0 id. Right?
With that assumption in mind I changed the where clause to this
(CASE
WHEN #someId = 0 THEN 1
WHEN SomeId = #someId THEN 1
ELSE 0
END = 1)
hoping that this will force evaluation order. But I'm wrong. I'm getting the deadlock again.
I've attached the deadlock graph below. I've renamed tables and sprocs involved (Company policy)
Question3 : Do you know what I'm missing here?
<deadlock-list>
<deadlock victim="process722c508">
<process-list>
<process id="process722c508" taskpriority="0" logused="0" waitresource="KEY: 6:72057594098810880 (ffffffffffff)" waittime="6217" ownerId="24219001" transactionname="SELECT" lasttranstarted="2011-05-17T03:29:16.033" XDES="0x80073a40" lockMode="RangeS-S" schedulerid="13" kpid="20436" status="suspended" spid="91" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2011-05-17T03:29:16.033" lastbatchcompleted="2011-05-17T03:29:16.033" clientapp=".Net SqlClient Data Provider" hostname="SOMEHOST" hostpid="28820" loginname="someloginname" isolationlevel="serializable (4)" xactid="24219001" currentdb="6" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
<executionStack>
<frame procname="fnGetTableResultAByBId" line="44" stmtstart="2246" stmtend="3566" sqlhandle="0x03000600800d7f0bda124000d99e00000000000000000000">
INSERT INTO #ReturnTable
SELECT Foo, Bar
FROM TheOneTable
WHERE ZId = #zId
AND (CASE
WHEN #yId = 0 THEN 1
WHEN YId = #yId THEN 1
ELSE 0
END = 1)
AND (CASE
WHEN #xId = 0 THEN 1
WHEN XId = #xId THEN 1
ELSE 0
END = 1) </frame>
<frame procname="GetViewCByDId" line="9" stmtstart="272" stmtend="2984" sqlhandle="0x03000600c21629025d8f3f00d99e00000100000000000000">
</frame>
</executionStack>
<inputbuf>
Proc [Database Id = 6 Object Id = 36247234] </inputbuf>
</process>
<process id="process7185048" taskpriority="0" logused="0" waitresource="KEY: 6:72057594098810880 (ffffffffffff)" waittime="6217" ownerId="24218992" transactionname="SELECT" lasttranstarted="2011-05-17T03:29:16.030" XDES="0x179980430" lockMode="RangeS-S" schedulerid="13" kpid="30616" status="suspended" spid="79" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2011-05-17T03:29:16.030" lastbatchcompleted="2011-05-17T03:29:16.030" clientapp=".Net SqlClient Data Provider" hostname="SOMEHOST" hostpid="28820" loginname="someloginname" isolationlevel="serializable (4)" xactid="24218992" currentdb="6" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
<executionStack>
<frame procname="fnGetTableResultAByBId" line="44" stmtstart="2246" stmtend="3566" sqlhandle="0x03000600800d7f0bda124000d99e00000000000000000000">
INSERT INTO #ReturnTable
SELECT Foo, Bar
FROM TheOneTable
WHERE ZId = #zId
AND (CASE
WHEN #yId = 0 THEN 1
WHEN YId = #yId THEN 1
ELSE 0
END = 1)
AND (CASE
WHEN #xId = 0 THEN 1
WHEN XId = #xId THEN 1
ELSE 0
END = 1) </frame>
<frame procname="GetViewCByDId" line="9" stmtstart="272" stmtend="2984" sqlhandle="0x03000600c21629025d8f3f00d99e00000100000000000000">
</frame>
</executionStack>
<inputbuf>
Proc [Database Id = 6 Object Id = 36247234] </inputbuf>
</process>
<process id="process7223048" taskpriority="0" logused="0" waitresource="KEY: 6:72057594098810880 (ffffffffffff)" waittime="5330" ownerId="24235090" transactionname="SELECT" lasttranstarted="2011-05-17T03:29:16.927" XDES="0x840d3b30" lockMode="RangeS-S" schedulerid="15" kpid="23452" status="suspended" spid="88" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2011-05-17T03:29:16.927" lastbatchcompleted="2011-05-17T03:29:16.927" clientapp=".Net SqlClient Data Provider" hostname="SOMEHOST" hostpid="28820" loginname="someloginname" isolationlevel="serializable (4)" xactid="24235090" currentdb="6" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
<executionStack>
<frame procname="GetOneRowEByFId" line="11" stmtstart="260" stmtend="2456" sqlhandle="0x03000600db082c08ba823f00d99e00000100000000000000">
SELECT TOP 1
Col1, Col2, Col3
FROM The2ndTable
INNER JOIN [dbo].[TheOneTable] ON [dbo].[TheOneTable].[LinkBetweenOneAndTwoId]=[The2ndTable].[LinkBetweenOneAndTwoId]
WHERE [dbo].[TheOneTable].ZId= #ActivityId and
[TheOneTable].[n
</frame>
</executionStack>
<inputbuf>
Proc [Database Id = 6 Object Id = 137103579] </inputbuf>
</process>
<process id="process6334088" taskpriority="0" logused="0" waitresource="KEY: 6:72057594098810880 (ffffffffffff)" waittime="5668" ownerId="24229434" transactionname="SELECT" lasttranstarted="2011-05-17T03:29:16.587" XDES="0x17ea9ac90" lockMode="RangeS-S" schedulerid="12" kpid="5104" status="suspended" spid="86" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2011-05-17T03:29:16.587" lastbatchcompleted="2011-05-17T03:29:16.587" clientapp=".Net SqlClient Data Provider" hostname="SOMEHOST" hostpid="28820" loginname="someloginname" isolationlevel="serializable (4)" xactid="24229434" currentdb="6" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
<executionStack>
<frame procname="GetOneRowEByFId" line="11" stmtstart="260" stmtend="2456" sqlhandle="0x03000600db082c08ba823f00d99e00000100000000000000">
SELECT TOP 1
Col1, Col2, Col3
FROM The2ndTable
INNER JOIN [dbo].[TheOneTable] ON [dbo].[TheOneTable].[LinkBetweenOneAndTwoId]=[The2ndTable].[LinkBetweenOneAndTwoId]
WHERE [dbo].[TheOneTable].ZId= #ActivityId and
[TheOneTable].[n</frame>
</executionStack>
<inputbuf>
Proc [Database Id = 6 Object Id = 137103579] </inputbuf>
</process>
<process id="process8808e08" taskpriority="0" logused="0" waitresource="KEY: 6:72057594098810880 (ffffffffffff)" waittime="6652" ownerId="24217112" transactionname="SELECT" lasttranstarted="2011-05-17T03:29:15.610" XDES="0x833b5ca0" lockMode="RangeS-S" schedulerid="1" kpid="19752" status="suspended" spid="89" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2011-05-17T03:29:15.610" lastbatchcompleted="2011-05-17T03:29:15.610" clientapp=".Net SqlClient Data Provider" hostname="SOMEHOST" hostpid="28820" loginname="someloginname" isolationlevel="serializable (4)" xactid="24217112" currentdb="6" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
<executionStack>
<frame procname="GetOneRowEByFId" line="11" stmtstart="260" stmtend="2456" sqlhandle="0x03000600db082c08ba823f00d99e00000100000000000000">
SELECT TOP 1
Col1, Col2, Col3
FROM The2ndTable
INNER JOIN [dbo].[TheOneTable] ON [dbo].[TheOneTable].[LinkBetweenOneAndTwoId]=[The2ndTable].[LinkBetweenOneAndTwoId]
WHERE [dbo].[TheOneTable].ZId= #ActivityId and
[TheOneTable].[n
</frame>
</executionStack>
<inputbuf>
Proc [Database Id = 6 Object Id = 137103579] </inputbuf>
</process>
<process id="process5c08988" taskpriority="0" logused="1644" waitresource="KEY: 6:72057594098810880 (91a0638558d2)" waittime="4889" ownerId="24214248" transactionname="user_transaction" lasttranstarted="2011-05-17T03:29:15.327" XDES="0x186609470" lockMode="RangeI-N" schedulerid="9" kpid="9000" status="suspended" spid="102" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2011-05-17T03:29:15.330" lastbatchcompleted="2011-05-17T03:29:15.330" clientapp=".Net SqlClient Data Provider" hostname="SOMEHOST" hostpid="28820" loginname="someloginname" isolationlevel="serializable (4)" xactid="24214248" currentdb="6" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
<executionStack>
<frame procname="InsertIntoTheOneTable" line="25" stmtstart="1334" stmtend="2608" sqlhandle="0x03000600bbbacb5d25883f00d99e00000100000000000000">
INSERT INTO [dbo].[TheOneTable] (Some,Col,Here)
VALUES (#some,#col,#here) </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 6 Object Id = 1573632699] </inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057594098810880" dbid="6" objectname="TheOneTable" indexname="PK_TheOneTable" id="lock6b17a00" mode="RangeI-N" associatedObjectId="72057594098810880">
<owner-list />
<waiter-list>
<waiter id="process722c508" mode="RangeS-S" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="72057594098810880" dbid="6" objectname="TheOneTable" indexname="PK_TheOneTable" id="lock6b17a00" mode="RangeI-N" associatedObjectId="72057594098810880">
<owner-list />
<waiter-list>
<waiter id="process7185048" mode="RangeS-S" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="72057594098810880" dbid="6" objectname="TheOneTable" indexname="PK_TheOneTable" id="lock6b17a00" mode="RangeI-N" associatedObjectId="72057594098810880">
<owner-list />
<waiter-list>
<waiter id="process7223048" mode="RangeS-S" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="72057594098810880" dbid="6" objectname="TheOneTable" indexname="PK_TheOneTable" id="lock6b17a00" mode="RangeI-N" associatedObjectId="72057594098810880">
<owner-list />
<waiter-list>
<waiter id="process6334088" mode="RangeS-S" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="72057594098810880" dbid="6" objectname="TheOneTable" indexname="PK_TheOneTable" id="lock6b17a00" mode="RangeI-N" associatedObjectId="72057594098810880">
<owner-list>
<owner id="process5c08988" mode="RangeI-N" />
</owner-list>
<waiter-list>
<waiter id="process8808e08" mode="RangeS-S" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="72057594098810880" dbid="6" objectname="TheOneTable" indexname="PK_TheOneTable" id="lock6372e80" mode="RangeS-S" associatedObjectId="72057594098810880">
<owner-list>
<owner id="process7223048" mode="RangeS-S" />
<owner id="process6334088" mode="RangeS-S" />
</owner-list>
<waiter-list>
<waiter id="process5c08988" mode="RangeI-N" requestType="wait" />
</waiter-list>
</keylock>
</resource-list>
</deadlock>
</deadlock-list>
In the context of locking, tables and their related indexes are separate entities. At times, dead locking happens between a table and its index, rather than between two separate tables.
The problem is most likely when a lock is aquired on an index and then another lock is aquired on the related table (i.e. bar) to do the data lookup. During the insert, this will happen in the opposite order. First, the table (i.e. bar) is locked and updated, then indexes are locked.
select foo
from bar
where #someId = 0 OR SomeId = #someId
Do you have/can you add a covering index (to help with the select) that contains both the SomeId and foo ? This way you'll avoid the lookup altogether and stop the problem from occuring.
Can you post the query plans rather than deadlock frames?
Would you mind trying some alternate criteria? I've been playing with this method lately (only I use NULLs not 0 to mean all values):
SET #yId = NullIf(#yId, 0);
SET #xId = NullIf(#xId, 0);
...
WHERE
#yId BETWEEN Coalesce(#yId, 0) AND Coalesce(#yId, 2147483647)
AND #xId BETWEEN Coalesce(#xId, 0) AND Coalesce(#xId, 2147483647)
Or you could use your zeroes intact:
WHERE
#yId BETWEEN #yId AND Coalesce(NullIf(#yId, 0), 2147483647)
AND #xId BETWEEN #xId AND Coalesce(NullIf(#xId, 0), 2147483647)
Thinking about this a little more... just to review, deadlocks only occur because of conflicting resource acquisition order. A resource is not just a table but rows, extents, pages, etc. If two queries are being submitted at once that initially acquire a smaller granularity lock, then escalate their locks to a something that overlaps the smaller lock the other process has, then you get a deadlock.
So, is there any way you can either acquire the larger lock earlier, avoid acquiring the larger conflicting lock, or change the resource acquisition order?
You could experiment with using WITH (TABLOCKX) which sounds horrible, but if your #yId or #xId is 0 thus making you select all rows, you're going to need the whole table anyway.
Have you also considered trying OPTION (MAXDOP 1) just to see if it helps? Theoretically, having multiple streams for the same data request could increase the likelihood of conflicting locks being acquired simultaneously.
Does the table have a clustered index? If not, add it, and if so, is it being used or can you force it to be used? This potentially could make the queries access the table in a different way, preventing the deadlock.
Post your comments and I'll see if any more ideas come up based on your responses.

SQL server update statements cause deadlocks

I have an application which is running multiple sql statements simultaneously in different threads, causing various deadlocks which all seem to come from one table. For example the 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 = ''
produce 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 realise some amount of deadlocks are inevitable and the application should handle them (which it does), but I don't understand why they should be happening in this case. In my simplistic mind these two statements should be locking different rows, and even if they were updating the same row, one should just wait for the other.
Can anyone explain why they are causing deadlocks, or give any suggestions as to how to prevent them?
We have 3 non-clustered indexes on the table (PID, ACTIVITYID, ITEMID, TRANID), (ITEMID), and (PID, ACTIVITYID). (PID, ACTIVITYID, ITEMID, TRANID) form the primary key. I've tried (somewhat blindly) playing about with the indexes, but seemingly to no avail.
The application is running on weblogic and sql server 2005, and I've reproduced the deadlocks on websphere and sql server 2008. The don't seem to occur when using an oracle database, but this is unfortunately not an option for our client!
Many thanks to anyone who can offer help or insight into this.
Problem are usually not updates alone, but combination of selects and updates. Consider scenario, where transaction selects some row and then updates it. If two such transactions run parallel, deadlock occurs.
Simplest solution is use UPDLOCK (and optionally ROWLOCK) hint in select statements; of course only for records, updated after - otherwise you may end in slow application.
Is there any clustered index? Any indexed views? Any other indexes? The columns being updated don't appear to be in any indexes. Row-level locking should be fine, but something must be causing an escalation. The sets appear to be disjoint, but perhaps the pages are overlapping (hence my question about the choice of clustered index).
http://msdn.microsoft.com/en-us/library/ms184286.aspx