Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.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
Sql server SQL Server 2012中delete和update语句之间的死锁_Sql Server_Sql Server 2012_Database Deadlocks - Fatal编程技术网

Sql server SQL Server 2012中delete和update语句之间的死锁

Sql server SQL Server 2012中delete和update语句之间的死锁,sql-server,sql-server-2012,database-deadlocks,Sql Server,Sql Server 2012,Database Deadlocks,我在两个存储过程之间的数据库中遇到了一个问题,一个试图更新,另一个想要删除大量数据 我的Offer表包含5000万行我知道这不是一个好的做法,我正在清除数据 该表包含一个增量ID,而不是一个主键,主键上有聚集索引 xml_死锁_报告: <event name="xml_deadlock_report" package="sqlserver" timestamp="2018-01-02T00:56:16.360Z"> <data name="xml_report"&g

我在两个存储过程之间的数据库中遇到了一个问题,一个试图更新,另一个想要删除大量数据

我的Offer表包含5000万行我知道这不是一个好的做法,我正在清除数据

该表包含一个增量ID,而不是一个主键,主键上有聚集索引

xml_死锁_报告:

  <event name="xml_deadlock_report" package="sqlserver" timestamp="2018-01-02T00:56:16.360Z">
    <data name="xml_report">
        <type name="xml" package="package0" />
        <value>
            <deadlock>
                <victim-list>
                    <victimProcess id="process3697498" />
                </victim-list>
                <process-list>
                    <process id="process3697498" taskpriority="0" logused="127362200" waitresource="PAGE: 9:1:99977592 " waittime="6212" ownerId="32514985656" transactionname="DELETE" lasttranstarted="2018-01-02T01:55:56.853" XDES="0x902e53ed28" lockMode="IX" schedulerid="5" kpid="10104" status="suspended" spid="155" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-01-02T00:00:02.427" lastbatchcompleted="2018-01-02T00:00:02.427" lastattention="1900-01-01T00:00:00.427" clientapp="SQLAgent - TSQL JobStep (Job 0xAF5CC7B9127279438B52607063734954 : Step 1)" hostname="HB01-BOSQL-CL02" hostpid="5008" loginname="RUEDUCOMMERCE\hicham.boutaleb" isolationlevel="read committed (2)" xactid="32514985656" currentdb="9" lockTimeout="4294967295" clientoption1="671088928" clientoption2="128056">
                        <executionStack>
                            <frame procname="EchangesDb.dbo.PurgeGM2" line="433" stmtstart="57518" stmtend="57750" sqlhandle="0x03000900c9c6d33469f20e0158a8000001000000000000000000000000000000000000000000000000000000">
DELETE 
                TOP (100000)
                OFFER
            WHERE
                ID IN (SELECT ID FROM #OFFERSTODELETE)
             OPTION(MAXDOP 1)    
                            </frame>
                            <frame procname="adhoc" line="1" sqlhandle="0x010009008b23cd0690ffbc006500000000000000000000000000000000000000000000000000000000000000">
Exec PurgeGM2    </frame>
                        </executionStack>
                        <inputbuf>
Exec PurgeGM2   </inputbuf>
                    </process>
                    <process id="process5b230c8" taskpriority="0" logused="183626528" waitresource="PAGE: 9:1:99056248 " waittime="2010" ownerId="32514934129" transactionname="user_transaction" lasttranstarted="2018-01-02T01:55:46.243" XDES="0xd0e49f16c0" lockMode="U" schedulerid="15" kpid="10684" status="suspended" spid="128" sbid="0" ecid="22" priority="0" trancount="0" lastbatchstarted="2018-01-02T01:55:46.240" lastbatchcompleted="2018-01-02T01:55:46.240" lastattention="1900-01-01T00:00:00.240" clientapp=".Net SqlClient Data Provider" hostname="HB01-BIZTALK01" hostpid="2620" isolationlevel="read committed (2)" xactid="32514934129" currentdb="9" lockTimeout="4294967295" clientoption1="673317152" clientoption2="128056">
                        <executionStack>
                            <frame procname="EchangesDb.dbo.offer_insert_diff" line="183" stmtstart="8450" stmtend="8780" sqlhandle="0x0300090048642c329947700146a8000001000000000000000000000000000000000000000000000000000000">
UPDATE o
            SET tc_process_status = 0
            FROM [dbo].[offer] AS o WITH(NOLOCK)
            INNER JOIN Temp_OffersToMove AS t WITH(NOLOCK) ON (o.offer_id = t.offer_id)    </frame>
                        </executionStack>
                        <inputbuf>
Proc [Database Id = 9 Object Id = 841770056]   
                        </inputbuf>
                    </process>
                </process-list>
                <resource-list>
                    <pagelock fileid="1" pageid="99977592" dbid="9" subresource="FULL" objectname="EchangesDb.dbo.offer" id="lock3d70957380" mode="U" associatedObjectId="72057595568062464">
                        <owner-list>
                            <owner id="process5b230c8" mode="U" />
                        </owner-list>
                        <waiter-list>
                            <waiter id="process3697498" mode="IX" requestType="wait" />
                        </waiter-list>
                    </pagelock>
                    <pagelock fileid="1" pageid="99056248" dbid="9" subresource="FULL" objectname="EchangesDb.dbo.offer" id="lock6d7712ab80" mode="IX" associatedObjectId="72057595568062464">
                        <owner-list>
                            <owner id="process3697498" mode="IX" />
                        </owner-list>
                        <waiter-list>
                            <waiter id="process5b230c8" mode="U" requestType="wait" />
                        </waiter-list>
                    </pagelock>
                </resource-list>
            </deadlock>
        </value>
    </data>
</event>
Offer.Offer\u Id不是主键并不重要。锁定覆盖行、页或表,而不是列。如果表中的一个字段发生更改,则至少会锁定整行

根据其编写方式,我假设您的删除过程正在运行以下语句:

DELETE TOP (100000) OFFER
WHERE ID IN (
        SELECT ID
        FROM #OFFERSTODELETE
        )
OPTION (MAXDOP 1)
在某种循环中,可能在每次迭代中都有提交和检查点,直到没有行被删除为止?而OFFERSTODELETE大概有几百万行

通过减少每次迭代中删除的行数,可以降低死锁的概率。比如说,100或500。这将减少锁的数量,并降低将锁升级为页锁或表锁的可能性。当然,这样做总体上需要更长的时间,但锁的负担会更少。如果您的用户都共享一个时区,那么在夜间运行删除也是一个好主意,甚至在计划的停机时间内运行删除更好。然后,您可以潜在地删除MAXDOP限制,而不必担心CPU的使用

除此之外,如果没有看到每个过程的完整性,就不可能提出任何建议。您可以重写这两个过程,这样它们就不会互相死锁。不幸的是,这并不总是可能的

此外:

我的Offer表包含5000万行我知道这不是一个好的做法,我正在清除数据


这么大的桌子没有什么内在的问题。说实话,它甚至不是特别大。如果您有一个好的集群索引,并且总是适当地过滤数据,那么就不会因为表的大小而对性能产生巨大影响。只要您在执行例行统计和索引维护,就不会有任何问题。

谢谢大家的帮助

我的问题通过建议和一些额外的工作得到了解决:

1减少批量找到好的三倍,对我来说是5000

2将清除的死锁优先级设置为低

3在Purgefor1025错误中添加死锁重试

4减少每次迭代后包含要删除行的my temp表的大小按id从order中删除top 5000

现在它工作得很好

许多小家伙