SQL Server тупик на соединительной таблице - PullRequest
0 голосов
/ 21 января 2019

Я столкнулся с тупиковой ситуацией в соединительной таблице, когда один процесс удаляет какую-то запись, а другой процесс выбирает другую запись (в 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
)

График взаимоблокировки выглядит следующим образом:

deadlock graph

График взаимоблокировки 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>

Правильно ли я понимаю, что возникла взаимоблокировкаиз-за процессов другой порядок блокировки страниц?Как я прочитал из здесь , одним из возможных решений является добавление индексов в поля FK Junction таблицы (это правильно?).Есть ли другое решение для этого, которого я не знаю?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...