Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.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_Deadlock - Fatal编程技术网

Sql server 如何解决非聚集索引上的插入/删除死锁?

Sql server 如何解决非聚集索引上的插入/删除死锁?,sql-server,deadlock,Sql Server,Deadlock,我遇到了一个死锁问题,我发现它是由两个存储过程引起的,这两个存储过程由不同的线程调用(2个称为web服务) 插入在X表中插入数据的sp 删除删除X表中数据的sp 此外,我得到的结果告诉我X表的非唯一和非聚集索引中发生了死锁。你有解决这个问题的办法吗 更新 从,我认为它是错误的,因为下面的陈述 在insert语句中,它获取id(聚集索引),然后获取非聚集索引 在delete语句中,它在id之前获取非聚集索引 因此,我需要像下面的语句一样为delete station选择id SELECT id

我遇到了一个死锁问题,我发现它是由两个存储过程引起的,这两个存储过程由不同的线程调用(2个称为web服务)

  • 插入在X表中插入数据的sp
  • 删除删除X表中数据的sp
  • 此外,我得到的结果告诉我X表的非唯一和非聚集索引中发生了死锁。你有解决这个问题的办法吗

    更新

    从,我认为它是错误的,因为下面的陈述

    • 在insert语句中,它获取id(聚集索引),然后获取非聚集索引
    • 在delete语句中,它在id之前获取非聚集索引
    因此,我需要像下面的语句一样为delete station选择id

    SELECT id FROM X WITH(NOLOCK) WHERE [condition]
    
    这两个存储过程都在事务中调用


    谢谢,存储过程是否修改了任何内容,或者只是执行读取?如果修改了某些内容,那么更新中是否有where子句,它们是否足够细粒度?如果您可以尝试以较小的批量更新行,那么SQL Server死锁的可能性较小,因为它只锁定少量索引,而不是整个索引


    如果可能的话,你能在这里发布死锁代码吗?如果存储过程太长,您能否在其中发布有问题的语句(如果您知道它们是哪一个的话)?

    没有死锁信息更多的是猜测,而不是正确的答案。。。可能是索引访问顺序问题,类似于。

    可能是select查询是实际问题,特别是如果它们在两个存储过程中是相同的表,但顺序不同。记住从表中读取将创建(共享)锁,这一点很重要。你可能想好好读一读

    正如Remus所说,同样的情况也可能发生在指数层面。他提供了一个很好的解释,但不幸的是,没有人找到一个神奇的解决方案,因为对于每种情况都没有一个单一的最佳解决方案


    我自己并不是这个领域的专家,但是使用,您可以确保相同的资源以相同的顺序锁定,防止死锁。不过,您可能需要测试人员提供更多信息来有效解决此问题。

    我们必须查看某种代码。。。你提到一笔交易;它处于什么隔离级别?要尝试的一件事是将
    (UPDLOCK)
    提示添加到用于查找行(或检查是否存在)的任何查询中;因此,您将从一开始就取出一个写锁(而不是读锁)


    当有争议时,这将导致(非常短暂的)阻塞而不是死锁。

    让应用程序恢复正常运行的快速方法是检测死锁错误(1205)并重新运行事务。这方面的代码可以在联机丛书的“TRY…CATCH”部分找到

    如果要删除和插入,则会影响聚集索引,并且表上的每个非聚集索引也需要有一个insert/delete。所以死锁发生的可能性绝对很大。首先,我想看看您的聚集索引是什么——例如,尝试为您的聚集索引设置一个代理键

    不幸的是,如果没有更多信息,几乎不可能完全解决死锁问题


    Rob

    你能发布死锁信息吗?我不能。我只知道上面的内容,我张贴。测试团队中的一些人只给我提供了很少的信息。虽然是我,我给你指出了读写文章,但我不能过早下结论。INSERT将插入一条新记录,因此它不会如此容易发生冲突。必须有更多的因素在起作用。也许是错误日志中的一些遗留信息?E在连接探查器并捕获死锁图的情况下重新编程?一个sp仅在X表中插入数据,另一个sp仅删除X表中的数据。但这两个sp都有一些调用其他表的不相关查询。这两行是否可能试图影响相同的行(即一行更新键值,而另一行尝试删除它)?否则,可以使用查询提示防止行级锁升级到更高级别的页级锁和表级锁。链接无效。请删除tp//I在同一个表上有两个并发的delete语句(delete FROM blah,其中id=unique to each thread)都需要聚集索引键锁,这可以通过使列非聚集或通过调用delete FROM blah WITH(UPDLOCK),其中id=N来解决。显然,提示告诉他们获取写锁而不是读锁。然而,我完全搞不懂为什么这是应用程序程序员的工作,而不是透明的@这很奇怪;通常,您会在较早的
    选择上使用
    UPDLOCK
    。我希望删除本身会自动作为更新锁发出。可能与钥匙范围锁定行为有关;你处于可序列化隔离级别吗?@Marc Gravell告诉我。该脚本调用READ_COMMITTED_SNAPSHOT ON,未配置ALLOW_SNAPSHOT_ISOLATION,并且似乎已关闭。如果我发现了什么地方出了问题(错误的ODBC调用或SQL配置!),我会尽量记住更新你们所有人,因为知道这一点通常是很好的。