none
死锁,让人崩溃。求救。 RRS feed

  • 问题

  • 数据库为英文版64位 sqlserver2008 R2

    表TA、TB、TC。
    TB表记录的是TA和TC记录之间的关联关系,TC和TA之间的关系为1..*,目前业务涉及的实际上是1..1.
    表TB字段为(A,C,B),A对应TA的主键值,C对应TC的主键值,B为描述字段。主键为PK_TB(C,A)

    我的程序是多线程的。
    每个线程批量处理更新表TC的工作,每个线程处理的TC记录集合之间没有交集。每个线程每次处理几十条TC表记录,每次批量作业由一个数据库事务进行保护,保证这批TC记录的更新同时成功或者同时失败。
    每个TC记录的更新作业过程如下:
    1、更新TC表自身属性。
    2、通过delete from TB where C='TC记录的主键值' 来先清除原有的TC和TA之间的关系。
    3、通过insert into TB(.....) 建立新的TC和TA之间的关系。
    ???
    以我的认识,每个线程之间处理的数据都无不相关。线程中每个TC记录的更新作业处理的数据之间也没有交集,不应该出现死锁啊。

    死锁图如下。鼠标悬停在两侧椭圆图形上是均显示下面蓝色部分:
    语句:
    (@P0 nvarchar(4000)) delete from TB where C=@p0



    • 已更改类型 Wang.Hui 2011年11月16日 13:49 死锁
    • 已编辑 Wang.Hui 2011年11月17日 14:05
    2011年11月16日 13:39

答案

  • All of them are exclusive locks on index except one on table, you can find out which index in which table with select object_name (nnn). Replace nnn with number in resource_associated_entity_id column.
    2011年11月18日 14:34

全部回复

  • Deadlock on pkey. Is it clustered? How many columns in it? You should check locks on that key when run your process.
    2011年11月16日 14:12
  • 这必须改写代码了。。。或者调整顺序,或者在查询时就指定UpdLock
    Try SQL Server 2008 QQ:315054403 dgdba@hotmail.com
    2011年11月17日 0:57
  • 先检查2楼的,如果不能改clustered,或者是clustered也deadlock,就只好用3楼的方案,不过这个会有block。
    想不想时已是想,不如不想都不想。
    2011年11月17日 4:16
    版主
  •  to rmiao:

    是聚簇索引。TB有3个字段,主键包含其中两个字段C和A。你说要我在运行时检查在主键上有多少锁,我不知道如何检查,如何操作呢?

    2011年11月17日 13:59
  • 先检查2楼的,如果不能改clustered,或者是clustered也deadlock,就只好用3楼的方案,不过这个会有block。
    想不想时已是想,不如不想都不想。


    其实处理过程比较简单,没有调整的余地了。

    同样的程序,数据库改成oracle 或者32位的中文sqlserver2005都没有问题,现在有点怀疑用的这个64位英文sqlserver2008 R2版有问题,明天打个sp1再试试。


    还有更加奇怪的事情,同样在sqlserver2008 R2,

    2、通过delete from TB where C='TC记录的主键值' 来先清除原有的TC和TA之间的关系。

     这个过程原先我是通过预编译方式发出的删除命令(也就是delete from TB where C=?,然后传入参数的方式删除),

    后来,当我将其换成直接拼接删除的sql语句(也就是"delete from TB where C='"+"xxx"+"'",)时,死锁居然消失。原本我做这个修改为的是能在死锁图中看到发生死锁的sql对应的字段C的值。

     

    现在我都头昏了,不知道我看到的这些是否都是表面现象。

    • 已编辑 Wang.Hui 2011年11月17日 14:16
    2011年11月17日 14:03
  •  to rmiao:

    是聚簇索引。TB有3个字段,主键包含其中两个字段C和A。你说要我在运行时检查在主键上有多少锁,我不知道如何检查,如何操作呢?

    You can use sp_lock for this.
    2011年11月17日 14:07
  •  to rmiao:

    是聚簇索引。TB有3个字段,主键包含其中两个字段C和A。你说要我在运行时检查在主键上有多少锁,我不知道如何检查,如何操作呢?

    You can use sp_lock for this.

    你要看的是锁的数量还是类型。我大概有40个线程同时在做这些操作。
    2011年11月17日 14:18
  • You can find what kind of locks put on the table when run the app, or can query sys.dm_tran_locks for specific info.
    2011年11月17日 14:26
  • 可能是bug呢,可以联系GTSC。你先检查下lock。
    想不想时已是想,不如不想都不想。
    2011年11月18日 4:55
    版主
  • You can find what kind of locks put on the table when run the app, or can query sys.dm_tran_locks for specific info.

    下面两张图片是我在程序运行时做了查询。 dbid=15 的数据库就是出问题的那个。

    2011年11月18日 11:40
  • All of them are exclusive locks on index except one on table, you can find out which index in which table with select object_name (nnn). Replace nnn with number in resource_associated_entity_id column.
    2011年11月18日 14:34