Wir haben eine Anwendung, die Daten in eine Tabelle einfügt. Leider bekommen wir Deadlocks und die Deadlocks kommen nur von Inserts. Wir sehen, dass die Einfügungen Schlüsselsperren in einer anderen Reihenfolge für einen nicht gruppierten Index annehmen, was das Problem verursacht.
Warum verhalten sich die Einsätze so und was sollten wir tun, um die Deadlocks zu lindern? Jede Hilfe oder Einsicht wird geschätzt.
Im folgenden Beispiel sind nur zwei Einfügungen beteiligt, es waren jedoch bis zu 4 verschiedene Einfügungen an einem Deadlock beteiligt.
Hier ist das Deadlock-Diagramm:
<deadlock>
<victim-list>
<victimProcess id="process3ab355868" />
</victim-list>
<process-list>
<process id="process3ab355868" taskpriority="0" logused="1184" waitresource="KEY: 5:72057594043629568 (6234ed5bf036)" waittime="7493" ownerId="92332106" transactionname="implicit_transaction" lasttranstarted="2014-10-13T12:37:43.060" XDES="0x123699668" lockMode="X" schedulerid="3" kpid="3540" status="suspended" spid="89" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2014-10-13T12:37:44.333" lastbatchcompleted="2014-10-13T12:37:44.333" lastattention="1900-01-01T00:00:00.333" clientapp="Microsoft JDBC Driver for SQL Server" hostname="" hostpid="0" loginname="" isolationlevel="read committed (2)" xactid="92332106" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="278" stmtend="818" sqlhandle="0x0200000053a65d302154b91e9fee55234669030a42479c050000000000000000000000000000000000000000">
INSERT INTO table (col1, col2, col3, col4, col5, col6, col7, col8, col9) VALUES (@P0, @P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8)
</frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown
</frame>
</executionStack>
<inputbuf>
(@P0 datetime2,@P1 nvarchar(4000),@P2 nvarchar(4000),@P3 datetime2,@P4 nvarchar(4000),@P5 nvarchar(4000),@P6 decimal(38,1),@P7 int,@P8 int)INSERT INTO table (col1, col2, col3, col4, col5, col6, col7, col8, col9) VALUES (@P0, @P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8) select SCOPE_IDENTITY() AS GENERATED_KEYS
</inputbuf>
</process>
<process id="process14b38c928" taskpriority="0" logused="2564" waitresource="KEY: 5:72057594043629568 (275232b7b238)" waittime="7491" ownerId="92325909" transactionname="implicit_transaction" lasttranstarted="2014-10-13T12:37:39.567" XDES="0x16b38b988" lockMode="X" schedulerid="3" kpid="3668" status="suspended" spid="65" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2014-10-13T12:37:44.337" lastbatchcompleted="2014-10-13T12:37:44.337" lastattention="1900-01-01T00:00:00.337" clientapp="Microsoft JDBC Driver for SQL Server" hostname="" hostpid="0" loginname="" isolationlevel="read committed (2)" xactid="92325909" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="278" stmtend="818" sqlhandle="0x0200000053a65d302154b91e9fee55234669030a42479c050000000000000000000000000000000000000000">
INSERT INTO table (col1, col2, col3, col4, col5, col6, col7, col8, col9) VALUES (@P0, @P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8)
</frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown
</frame>
</executionStack>
<inputbuf>
(@P0 datetime2,@P1 nvarchar(4000),@P2 nvarchar(4000),@P3 datetime2,@P4 nvarchar(4000),@P5 nvarchar(4000),@P6 decimal(38,1),@P7 int,@P8 int)INSERT INTO table (col1, col2, col3, col4, col5, col6, col7, col8, col9) VALUES (@P0, @P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8) select SCOPE_IDENTITY() AS GENERATED_KEYS
</inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057594043629568" dbid="5" objectname="table1" indexname="unique_index" id="lock17bc3a480" mode="X" associatedObjectId="72057594043629568">
<owner-list>
<owner id="process14b38c928" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process3ab355868" mode="X" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="72057594043629568" dbid="5" objectname="table1" indexname="unique_index" id="lock10735ce00" mode="X" associatedObjectId="72057594043629568">
<owner-list>
<owner id="process3ab355868" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process14b38c928" mode="X" requestType="wait" />
</waiter-list>
</keylock>
</resource-list>
</deadlock>
Hier ist die Tabelle DDL:
CREATE TABLE [table1](
[col0] [int] IDENTITY(1,1) NOT NULL,
[col1] [int] NOT NULL,
[col2] [int] NOT NULL,
[col3] [decimal](15, 4) NULL,
[col4] [datetime2](7) NOT NULL,
[col5] [varchar](8) NOT NULL,
[col6] [varchar](30) NOT NULL,
[col7] [datetime2](7) NOT NULL,
[col8] [varchar](8) NOT NULL,
[col9] [varchar](30) NOT NULL,
CONSTRAINT [PK] PRIMARY KEY CLUSTERED
(
[col0] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [unique_index] UNIQUE NONCLUSTERED
(
[col2] ASC,
[col1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE table1 ADD DEFAULT (sysdatetime()) FOR [col4]
GO
ALTER TABLE table1 ADD DEFAULT (sysdatetime()) FOR [col7]
GO