锁分区死锁

4
我有一张表,大约有350万行。数据库启用了锁分区[1]。这个表在白天会插入很多数据,我在锁定分区上遇到了很多死锁。这些类型的死锁在http://sqlindian.com/2012/07/07/deadlocks-involving-lock-partitions/上有描述,但作者说这些类型的死锁极为罕见。在我们的情况下,它们似乎并不罕见!
我可以通过跟踪标志1229禁用锁定分区,但这并不推荐。有人能给我一些建议,如何避免这些类型的死锁,或者我该如何进一步分析情况,看看为什么我们会遇到这么多这种“罕见”的死锁吗?
[1]http://msdn.microsoft.com/en-us/library/ms187504(v=sql.105).aspx 更新:添加死锁图例
<deadlock>
  <victim-list>
    <victimProcess id="process5004748" />
  </victim-list>
  <process-list>
    <process id="process5004748" taskpriority="0" logused="0" waitresource="OBJECT: 5:1423344135:0 " waittime="3008" ownerId="2379819613" transactionname="user_transaction" lasttranstarted="2013-03-14T09:28:55.803" XDES="0x77ab8f950" lockMode="X" schedulerid="11" kpid="5416" status="suspended" spid="507" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2013-03-14T09:28:55.817" lastbatchcompleted="2013-03-14T09:28:55.807" clientapp=".Net SqlClient Data Provider" hostname="ExampleHost" hostpid="8664" loginname="ExampleUser" isolationlevel="read uncommitted (1)" xactid="2379819613" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="" line="1" stmtstart="616" stmtend="1504" sqlhandle="0x020000002468011b993c824e2e0ce3fd2783a30e8e591641" />
        <frame procname="" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000" />
      </executionStack>
      <inputbuf>
(@p0 datetime,@p1 bigint ...) INSERT INTO tblExample (Column1, Column2, ...); select SCOPE_IDENTITY()   
      </inputbuf>
    </process>
    <process id="processd4a988" taskpriority="0" logused="0" waitresource="OBJECT: 5:1423344135:10 " waittime="3008" ownerId="2379819595" transactionname="user_transaction" lasttranstarted="2013-03-14T09:28:55.663" XDES="0x2fe4323b0" lockMode="X" schedulerid="2" kpid="6756" status="suspended" spid="473" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2013-03-14T09:28:55.677" lastbatchcompleted="2013-03-14T09:28:55.667" clientapp=".Net SqlClient Data Provider" hostname="ExampleHost" hostpid="8664" loginname="ExampleUser" isolationlevel="read uncommitted (1)" xactid="2379819595" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="" line="1" stmtstart="616" stmtend="1504" sqlhandle="0x020000002468011b993c824e2e0ce3fd2783a30e8e591641" />
        <frame procname="" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000" />
      </executionStack>
      <inputbuf>
        (@p0 datetime,@p1 bigint ...) INSERT INTO tblExample (Column1, Column2, ...); select SCOPE_IDENTITY()
      </process>
  </process-list>
  <resource-list>
    <objectlock lockPartition="0" objid="1423344135" subresource="FULL" dbid="5" objectname="" id="lock5d745ae00" mode="X" associatedObjectId="1423344135">
      <owner-list>
        <owner id="processd4a988" mode="X" />
      </owner-list>
      <waiter-list>
        <waiter id="process5004748" mode="X" requestType="wait" />
      </waiter-list>
    </objectlock>
    <objectlock lockPartition="10" objid="1423344135" subresource="FULL" dbid="5" objectname="" id="lock55da8ea00" mode="IX" associatedObjectId="1423344135">
      <owner-list>
        <owner id="process5004748" mode="IX" />
      </owner-list>
      <waiter-list>
        <waiter id="processd4a988" mode="X" requestType="wait" />
      </waiter-list>
    </objectlock>
  </resource-list>
</deadlock>

更新 2:添加由 NHibernate 生成的 INSERT

begin transaction with isolation level: ReadUncommitted

INSERT INTO tblExample
            (Column1,
             Column2,
             Column2,
             Column3,
             Column4,
             Column5,
             Column6,
             Column7,
             Column8,
             Column9,
             Column10,
             Column11,
             Column12,
             Column13,
             Column14,
             Column15,
             Column16,
             Column17,
             Column18,
             Column19,
             Column20,
             Column21)
VALUES      ('2013-03-14T12:47:26.00' /* @p0 */,
             NULL /* @p1 */,
             75 /* @p2 */,
             'Test Text with some characters' /* @p3 */,
             'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.152 Safari/537.22' /* @p4 */,
             2130706433 /* @p5 */,
             NULL /* @p6 */,
             NULL /* @p7 */,
             0 /* @p8 */,
             'Test Title' /* @p9 */,
             '11223344' /* @p10 */,
             0 /* @p11 */,
             '2013-03-14T12:47:26.00' /* @p12 */,
             0 /* @p13 */,
             '2013-03-14T12:47:26.00' /* @p14 */,
             'en' /* @p15 */,
             '2013-03-14T12:47:26.00' /* @p16 */,
             0 /* @p17 */,
             'SomeName' /* @p18 */,
             NULL /* @p19 */,
             917278 /* @p20 */,
             2805683 /* @p21 */);



select SCOPE_IDENTITY()

commit transaction
2个回答

3
假设您已经进行了尽职调查(即,您正确地进行了调查),让我们明确一点,我们正在谈论锁定分区,而不是分区锁定
不幸的是,您无法做任何事情,只能确保您正在运行最新的SP和最新的CU。最好使用最新的产品版本。在这个领域有很多修复程序。如果您应用了最新的SP和最新的CU,问题仍然存在,请联系产品支持。

我可以使用跟踪标志1229禁用锁定分区,但这不被推荐。

你有多少核心?您总是可以尝试并测试。

是的,我肯定在谈论锁分区。我们的死锁图符合参考文章中的所有标准,锁定的对象形式为OBJECT 5:2342545:23,有lockPartition="n",subresource="FULL"等。我已经在原始帖子中添加了一个死锁图示例,以防您可以从中获取一些额外信息。 - Einar Egilsson
你能发布NHibernate生成的确切INSERT语句吗? - Remus Rusanu
1
READ UNCOMMITTED id 单独使用可能存在问题,但不应该对您的问题造成影响。 - Remus Rusanu
你能用SQL Profiler检查一下SQL实际看到了什么吗? - Remus Rusanu
终于有时间再次看这个了。SQL Profiler基本上可以看到INSERT INTO tblExample (Column1,...Column21 ) VALUES (@p0, ..., @p21); SELECT SCOPE_IDENTITY(); 。所有的值都是参数化的,以select scope identity结束。所以,非常简单的SQL语句。 - Einar Egilsson
显示剩余5条评论

2

我们遇到了类似的问题,在进行适当的调查后,发现主要问题是创建了一些没有启用row_lock和page_lock的索引。因此,对于影响该索引的任何插入、更新、删除操作都会在表级别生成X锁。并发操作最终导致死锁。

SELECT name indexname,allow_row_locks,allow_page_locks
FROM sys.indexes
WHERE 1=1 
--and object_id = object_id('tablename') 
AND allow_row_locks = 0 
AND allow_page_locks = 0

如果可以的话,我会给它加上100个赞;)今天在生产环境中,我们意外地使用行和页锁重新创建了一些索引,这实际上拯救了我们免于可怕的死锁。 - Juan Pablo Califano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接