我遇到一个联结表上的死锁,而一个进程删除了某些条目,而另一个进程选择了另一个条目(在SQL Server 2014中)。
模式如下:
CREATE TABLE Junction
(
JunctionId BIGINT IDENTITY(1,1) PRIMARY KEY,
Table1Id INT NOT NULL,
Table2Id INT NOT NULL,
FOREIGN KEY (Table1Id) REFERENCES Table1(Table1Id),
FOREIGN KEY (Table2Id) REFERENCES Table2(Table2Id)
)
CREATE TABLE Table1
(
Table1Id INT IDENTITY(1,1) PRIMARY KEY,
SomeData1 VARCHAR(30) NOT NULL
)
CREATE TABLE Table2
(
Table2Id INT IDENTITY(1,1) PRIMARY KEY,
SomeData2 VARCHAR(30) NOT NULL
)
死锁图看起来像这样:
死锁图xml:
<deadlock-list>
<deadlock victim="process18679f088">
<process-list>
<process id="process18679f088" taskpriority="0" logused="0"
waitresource="PAGE: 6:1:19957 " waittime="4855" ownerId="5887063"
transactionname="SELECT" lasttranstarted="2019-01-19T18:12:40.450"
XDES="0x1ba3aba20" lockMode="S" schedulerid="4" kpid="11756"
status="suspended" spid="63" sbid="0" ecid="0" priority="0"
trancount="0" lastbatchstarted="2019-01-19T18:12:40.450"
lastbatchcompleted="2019-01-19T18:12:40.453" lastattention="1900-01-
01T00:00:00.453" clientapp=".Net SqlClient Data Provider"
hostname="WIN-*****" hostpid="96380" loginname="WIN-
J***" isolationlevel="read committed (2)"
xactid="5887063" currentdb="6" lockTimeout="4294967295"
clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="GetSmth"
line="5" stmtstart="132" stmtend="1010"
sqlhandle="0x03000600ea777e2c037f2301bea9000001.....">
SELECT t2.Table2Id, SomeData2 FROM Table2 t2
INNER JOIN Junction j ON t2.Table2Id=j.Table2Id
WHERE Table1Id=@table1Id
</frame>
</executionStack>
<inputbuf> Proc [Database Id = 6 Object Id = 746485738]</inputbuf>
</process>
<process id="process1867be108" taskpriority="0" logused="363700"
waitresource="PAGE: 6:1:19956 " waittime="4021"
ownerId="5887012" transactionname="user_transaction"
lasttranstarted="2019-01-19T18:12:40.030" XDES="0x1c7aae700"
lockMode="X" schedulerid="2" kpid="85928" status="suspended"
spid="61" sbid="0" ecid="0" priority="0" trancount="2"
lastbatchstarted="2019-01-19T18:12:41.283"
lastbatchcompleted="2019-01-19T18:12:41.283"
lastattention="2019-01-19T18:12:40.413" clientapp=".Net
SqlClient Data Provider" hostname="WIN-****"
hostpid="96380" loginname="WIN-JFE5*****"
isolationlevel="read uncommitted (1)" xactid="5887012"
currentdb="6" lockTimeout="4294967295" clientoption1="671088672"
clientoption2="128056">
<executionStack>
<frame procname="RemoveSmth"
line="6" stmtstart="188" stmtend="386"
sqlhandle="0x03000600aef2cc644996e400c1a5000001.....">
DELETE FROM Junction
WHERE Table1Id=@table1Id AND Table2Id=@table2Id
</frame>
</executionStack>
<inputbuf> Proc [Database Id = 6 Object Id = 1691153070] </inputbuf>
</process>
</process-list>
<resource-list>
<pagelock fileid="1" pageid="19957" dbid="6" subresource="FULL"
objectname="Junction"
id="lock1af48eb80" mode="X"
associatedObjectId="72057594040614912">
<owner-list>
<owner id="process1867be108" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process18679f088" mode="S" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="19956" dbid="6" subresource="FULL"
objectname="Junction"
id="lock1af490200" mode="U"
associatedObjectId="72057594040614912">
<owner-list>
<owner id="process18679f088" mode="S"/>
</owner-list>
<waiter-list>
<waiter id="process1867be108" mode="X" requestType="convert"/>
</waiter-list>
</pagelock>
</resource-list>
</deadlock>
</deadlock-list>
我是否正确理解死锁是由于进程的页面阻塞顺序不同而导致的?正如我从here中所读到的,一种可能的解决方案是将索引添加到Junction表FK字段中(这对吗?)。还有我不知道的另一种解决方案吗?