死锁发生在删除插入场景中

Dum*_*per 2 sql-server

<deadlock-list>
  <deadlock victim="process14012e08">
    <process-list>
      <process id="process14012e08" taskpriority="0" logused="148" 
               waitresource="PAGE: 28:1:762341" waittime="6583" 
               ownerId="54542271281" transactionname="DELETE" 
               lasttranstarted="2013-06-22T01:04:20.450" XDES="0x64de49950" 
               lockMode="S" schedulerid="26" kpid="13336" status="suspended" spid="1239" 
               sbid="0" ecid="0" priority="0" trancount="2" 
               lastbatchstarted="2013-06-22T01:00:19.120" 
               lastbatchcompleted="2013-06-22T01:00:19.117" hostpid="15675" 
               isolationlevel="read committed (2)" xactid="54542271281" currentdb="28" 
               lockTimeout="4294967295" clientoption1="671350816" clientoption2="128056">
        <executionStack>
          <frame procname="adhoc" line="3" stmtstart="134" stmtend="332" 
                 sqlhandle="0x02000000e5eb1a38144fa5c164b3c876cc2c8da059bf3bb1">
            delete from grid_col where grid_col_id not in (select grid_col_id from grid)
          </frame>
        </executionStack>
        <inputbuf>
          set rowcount 10000
          while 1 = 1
          begin delete from grid_col where grid_col_id not in (select grid_col_id from grid)
          if @@rowcount = 0
          break
          end
          set rowcount 0
        </inputbuf>
      </process>
      <process id="process10031288" taskpriority="0" logused="912" 
               waitresource="OBJECT: 28:731149650:16 " waittime="40270" 
               ownerId="54542276360" transactionname="insertRows" 
               lasttranstarted="2013-06-22T01:04:23.753" XDES="0x1641ef9400" 
               lockMode="IS" schedulerid="17" kpid="29104" status="suspended" spid="351" 
               sbid="0" ecid="0" priority="0" trancount="2" 
               lastbatchstarted="2013-06-22T01:04:23.753" 
               lastbatchcompleted="2013-06-22T01:04:23.660" 
               isolationlevel="read committed (2)" xactid="54542276360" 
               lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
        <executionStack>
          <frame procname="check_grid_col" line="1" stmtstart="226" stmtend="376" 
                 sqlhandle="0x03001c00fe2706376157a70026a000000000000000000000">
            SELECT @retval = COUNT(*) from grid_col where grid_col_id = @grid_col
          </frame>
          <frame procname="adhoc" line="1" stmtstart="34376" stmtend="35270" 
                 sqlhandle="0x02000000434dff26c45f91c6fdb640bbbf3a4a276f6ac605">
            INSERT INTO grid (grid_id,grid_col_id,value) VALUES ( @P2 , @grid_col_id,@P3)
          </frame>
        </executionStack>
        <inputbuf>
          (@P0 bigint,@P1 int,@P2 char(300))
        </inputbuf>
      </process>
    </process-list>
    <resource-list>
      <pagelock fileid="1" pageid="762341" dbid="28" objectname="grid" 
                id="lock1cb9187500" mode="IX" associatedObjectId="72057594070695936">
        <owner-list>
          <owner id="process10031288" mode="IX" />
        </owner-list>
        <waiter-list>
          <waiter id="process14012e08" mode="S" requestType="wait" />
        </waiter-list>
      </pagelock>
      <objectlock lockPartition="16" objid="731149650" subresource="FULL" 
                  dbid="28" objectname="grid_col" id="lock12e6c78f00" mode="X" 
                  associatedObjectId="731149650">
        <owner-list>
          <owner id="process14012e08" mode="X" />
        </owner-list>
        <waiter-list>
          <waiter id="process10031288" mode="IS" requestType="wait" />
        </waiter-list>
      </objectlock>
    </resource-list>
  </deadlock>
</deadlock-list>
Run Code Online (Sandbox Code Playgroud)

gbn*_*gbn 5

它是如何发生的一个例子:

两个进程,每个进程在同一页上都有一个共享锁,那么每个进程都需要一个排他锁。由于共享行锁,每个进程不能独占锁定页面。

因此,死锁发生在同一页面上。

更多来自@AlexK 的例子


Rem*_*anu 5

Page 28:1:762341 在 IX 模式下由 INSERT 拥有,在 S 模式下由 DELETE 通缉。对象 731149650 ( grid_col) 在 X 模式下由 DELETE 所有,在 IS 模式下由 INSERT 通缉(用于 CHECK SELECT)。

中的列有一个SELECT COUNT(*)from grid_colas 检查条件grid。和一个已弃用的 ROWCOUNT 限制反加入 DELETE,它似乎做扫描启动。换句话说,您正在乞求死锁

修复您的架构和数据设计。

  • 不要使用选择交叉表的检查条件。使用外键约束,改变数据模型设计以适应外键约束。
  • 使用 TOP 子句来限制 DELETE。
  • grid和上的索引很可能grid_col丢失或不正确。