Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
INSERT和SELECT语句之间的SQL server死锁_Sql_Sql Server_Sql Server 2005_Foreign Keys_Deadlock - Fatal编程技术网

INSERT和SELECT语句之间的SQL server死锁

INSERT和SELECT语句之间的SQL server死锁,sql,sql-server,sql-server-2005,foreign-keys,deadlock,Sql,Sql Server,Sql Server 2005,Foreign Keys,Deadlock,我在SQLServer2005上遇到了多个死锁问题。 这是介于INSERT和SELECT语句之间的语句 有两张桌子。表1和表2。表2将表1的PK(表1_id)作为外键。 表1\u id上的索引已聚集 插入操作一次在表2中插入一行。 SELCET连接两个表。(这是一个很长的查询,可能需要12秒才能运行) 根据我的理解(和实验),INSERT应该获得表1上的IS锁,以检查引用完整性(这不应该导致死锁)。但是,在本例中,它获得了一个IX页锁 报告: <deadlock-list> <

我在SQLServer2005上遇到了多个死锁问题。 这是介于INSERT和SELECT语句之间的语句

有两张桌子。表1和表2。表2将表1的PK(表1_id)作为外键。
表1\u id上的索引已聚集

插入操作一次在表2中插入一行。
SELCET连接两个表。(这是一个很长的查询,可能需要12秒才能运行)

根据我的理解(和实验),INSERT应该获得表1上的IS锁,以检查引用完整性(这不应该导致死锁)。但是,在本例中,它获得了一个IX页锁

报告:

<deadlock-list>
 <deadlock victim="process968898">
  <process-list>
   <process id="process8db1f8" taskpriority="0" logused="2424" waitresource="OBJECT: 5:789577851:0 " waittime="12390" ownerId="61831512" transactionname="user_transaction" lasttranstarted="2010-04-16T07:10:13.347" XDES="0x222a8250" lockMode="IX" schedulerid="1" kpid="3764" status="suspended" spid="52" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-04-16T07:10:13.350" lastbatchcompleted="2010-04-16T07:10:13.347" clientapp=".Net SqlClient Data Provider" hostname="VIDEV01-B-ME" hostpid="3040" loginname="DatabaseName" isolationlevel="read uncommitted (1)" xactid="61831512" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="DatabaseName.dbo.prcTable2_Insert" line="18" stmtstart="576" stmtend="1148" sqlhandle="0x0300050079e62d06e9307f000b9d00000100000000000000">
INSERT INTO dbo.Table2
    (
        f1,
        table1_id,
        f2
    )
    VALUES
    (
        @p1,
        @p_DocumentVersionID,
        @p1

    )     </frame>
    </executionStack>
    <inputbuf>
Proc [Database Id = 5 Object Id = 103671417]    </inputbuf>
   </process>
   <process id="process968898" taskpriority="0" logused="0" waitresource="PAGE: 5:1:46510" waittime="7625" ownerId="61831406" transactionname="INSERT" lasttranstarted="2010-04-16T07:10:12.717" XDES="0x418ec00" lockMode="S" schedulerid="2" kpid="1724" status="suspended" spid="53" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-04-16T07:10:12.713" lastbatchcompleted="2010-04-16T07:10:12.713" clientapp=".Net SqlClient Data Provider" hostname="VIDEV01-B-ME" hostpid="3040" loginname="DatabaseName" isolationlevel="read committed (2)" xactid="61831406" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="DatabaseName.dbo.prcGetList" line="64" stmtstart="3548" stmtend="11570" sqlhandle="0x03000500dbcec17e8d267f000b9d00000100000000000000">
         <!-- XXXXXXXXXXXXXX...SELECT STATEMENT WITH Multiple joins including   both Table2  table 1 and .... XXXXXXXXXXXXXXX -->
    </frame>
    </executionStack>
    <inputbuf>
Proc [Database Id = 5 Object Id = 2126630619]    </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <pagelock fileid="1" pageid="46510" dbid="5" objectname="DatabaseName.dbo.table1" id="lock6236bc0" mode="IX" associatedObjectId="72057594042908672">
    <owner-list>
     <owner id="process8db1f8" mode="IX"/>
    </owner-list>
    <waiter-list>
     <waiter id="process968898" mode="S" requestType="wait"/>
    </waiter-list>
   </pagelock>
   <objectlock lockPartition="0" objid="789577851" subresource="FULL" dbid="5" objectname="DatabaseName.dbo.Table2" id="lock970a240" mode="S" associatedObjectId="789577851">
    <owner-list>
     <owner id="process968898" mode="S"/>
    </owner-list>
    <waiter-list>
     <waiter id="process8db1f8" mode="IX" requestType="wait"/>
    </waiter-list>
   </objectlock>
  </resource-list>
 </deadlock>
</deadlock-list>

首先,我要说DatabaseName.dbo.prcTable2_Insert正在事务内部执行或显式打开一个事务,并且它(或与打开的事务的连接)已经事先插入到表1中。

I表示“意图”锁,它们总是与层次结构相关联。因为锁管理器不了解物理结构,所以他不可能遵守层次结构锁,因此在意向锁中重新创建层次结构

在您的情况下,INSERT在页面上有一个意图锁。这意味着它还获得了页面中某一行的X锁,这是正常行为。它现在尝试获取一个新的IX锁,因此可能需要在另一个页面中插入一行。这是插入到具有多个索引的表中的正常行为:第一个IX位于其中一个索引(可能是聚集索引)上,第二个IX位于非聚集索引上

您所说的选择在12秒钟内返回,因此这是一个长查询,在一个大数据集上,并且计划可能选择了一个高锁粒度,即页面锁。SELECT在INSERT需要IX锁的页面上有一个S锁,并且在INSERT需要IX锁的页面上有另一个S锁

这是一个微不足道的死锁,应该很容易修复:确保您的SELECT不需要这些页面S锁。这里没有插入错误。由于不知道选择是什么,我无法确定选择是否最优。根据我的经验,几乎所有像这样的选择都有很多、很多和更多的改进空间(无论是选择本身还是它下面的模式)

但接受“选择”是最佳选择,您最容易的出狱卡是打开:

ALTER数据库设置允许\u快照\u隔离打开;
将数据库设置为读取已提交快照打开;
更新:


实际上,在第二次阅读时,很明显INSERT在不同的表上有锁(除非您修改了XML,它看起来到处都是手工编辑的),因此您关于INSERT如何操作的解释肯定是错误的。INSERT是事务的一部分,它至少进行了两次写入,一次在表1上,一次在表2上。但这并不能改变问题和解决方案。确实可以将事务中的两次写入拆分为单独的事务,但这显然是最糟糕的方法。

可以为表和外键添加DDL语句吗?应该只有一次写入。我修改了xml以简化事情并删除一些敏感的名称。我想你让我走上了正确的道路。我发现一个事务在调用insert之后更新了TABLE1。但是锁的顺序对我来说还是没有意义。为什么它在需要之前就得到了IX锁?插入执行后,它不应该升级锁吗?顺便说一句,我自己仍然无法复制这个。我已经用这两个inset/updates创建了一个事务,在循环中运行,和用SELECT-one运行循环并行。有什么想法吗?@dtroy-我恐怕没有更多的建议,因为我没有复制它的能力(当然,如果你能复制它,我怀疑你在这里是否需要更多的帮助)。谢谢。我想你让我走对了方向。我发现了由于事务中存在锁而导致的死锁,这些事务调用了多个需要X锁的SP。不幸的是,我不知道如何在不使用快照隔离的情况下解决这个问题。你知道吗?有一种方法可以预先锁定你需要的所有对象,并且以某种方式原子化?更改锁的顺序与我无关,因为将有不同的读取SP以不同的顺序获取锁。长时间运行的事务和可变的锁顺序几乎总是导致死锁。如果您可以接受并发性的降低,那么强制插入使用完整的表锁(使用(TABLOCKX))可能会防止这种特定的死锁再次发生。或者,如果您的选择可以处理脏数据/缺少数据,那么使用readuncommitted或with(readpass)可能是一种方法。或最终解决方案—准备好系统以应对死锁,然后再次重试整个事务。
CREATE TABLE [dbo].[Table2] (
    [Table2_id] [int] IDENTITY (1, 1) NOT NULL ,
    [f1] [int] NULL ,
    [Table1_id] [int] NOT NULL ,
    [f2] [int] NOT NULL ,
)

ALTER TABLE [dbo].[Table2] ADD 
    CONSTRAINT [FK_Table2_Table1] FOREIGN KEY 
    (
        [Table1_id]
    ) REFERENCES [dbo].[Table1] (
        [Table1_id]
    )


CREATE TABLE [dbo].[Table1] (
    [Table1_id] [int] IDENTITY (1, 1) NOT NULL ,
)

ALTER TABLE [dbo].[Table1] WITH NOCHECK ADD 
    CONSTRAINT [PK_Table1] PRIMARY KEY  CLUSTERED 
    (
        [Table1_id]
    ) 
ALTER DATABASE <dbname> SET ALLOW_SNAPSHOT_ISOLATION ON;
ALTER DATABASE <dbname> SET READ_COMMITTED_SNAPSHOT ON;