0

请。我们已经在最近见证了流量大幅增加的生产数据库上获得了很多锁。我们使用 IdeaBlade 进行大部分数据访问。

我使用 Sql Profiler 得到了以下跟踪:

deadlock victim="process84af28"
  resource-list
    keylock hobtid="72057594096451584" dbid="6" objectname="cpc_db.dbo.Prefix_ChildTableName" indexname="PK_Prefix_ChildTableName" id="lock45982ac0" mode="X" associatedObjectId="72057594096451584"
      owner-list
owner id="processb852e8" mode="X" 
   owner-list
   waiter-list
    waiter id="process84af28" mode="S" requestType="wait" 
    waiter id="processb855b8" mode="RangeS-U" requestType="wait" 
   waiter-list
  keylock
  keylock hobtid="72057594096451584" dbid="6" objectname="cpc_db.dbo.Prefix_ChildTableName" indexname="PK_Prefix_ChildTableName" id="lock513c3bc0" mode="RangeS-U" associatedObjectId="72057594096451584"
   owner-list
    owner id="processb855b8" mode="RangeS-U" 
   owner-list
   waiter-list
    waiter id="processb852e8" mode="RangeS-U" requestType="wait" 
   waiter-list
  keylock
 resource-list
deadlock

任何人的想法?

我不是 DBA,但此跟踪似乎表明:

  1. 在子表中的一行上具有排他锁 X 的进程正在尝试在同一资源上获取 Select-Update 锁(似乎没有意义)

  2. 另一个具有 Select-Update 锁的进程仍在尝试获取 Select-Update 锁

澄清任何人?

我们如何才能最大限度地减少或消除死锁?

4

4 回答 4

1

首先要注意几点:

  1. 您正在使用可序列化的事务,这是最严格的悲观锁定形式。很有可能,您不需要这个(我们知道您正在使用可序列化事务,因为 KEY 锁仅适用于此隔离级别)。正如 Remus 上面提到的,您绝对应该在这里寻找其他选项。

  2. 上面的输出似乎被截断了一点,你应该有一些称为 process-list 的部分,其中包含将进程信息映射到 spid 和查询的信息

从上面的输出中可以看出:

processb852e8 owns an exclusive lock on index "cpc_db.dbo.Prefix_ChildTableName.PK_Prefix_ChildTableName"
    process84af28 is waiting for a shared KEY lock
    processb855b8 is also waiting for a Shared Range-Update KEY lock

processb855b8 owns Shared Range-Update lock on index "cpc_db.dbo.Prefix_ChildTableName.PK_Prefix_ChildTableName" (the same index)
    processb852e8 is waiting on a Shared Range-Update KEY lock

排他锁是某种写入(即更新、删除、插入),RangeS-U 锁很可能是更新,但没有看到映射的信息就无法判断。

Bart Duncan 有几篇关于破译跟踪输出的精彩文章,如果你掌握了这一切,请参阅第 1部分和第 2 部分您还可以在此处查看一般的并发性和脚本概述。

于 2009-11-11T01:11:08.063 回答
0

mode="RangeS-U"

范围锁定?停止使用高事务隔离级别。坚持阅读承诺。如果你使用 CLR TransactionScope 对象,让它们使用 Read Commited 隔离(默认情况下它们使用 Seralizable,哎呀)。尝试在数据库上打开已提交的读取快照隔离。请参阅使用快照隔离

于 2009-11-11T01:00:32.033 回答
0

我自己用不同的产品(不是 IdeaBlade)看到了这个死锁问题。以我的经验,这不是数据库问题;可能是软件与数据库通信的问题。

我的问题在于与数据库通信的组件的配置。

第一次,COM+ 默认为 SERIALIZABLE 并且必须配置为默认为 READ COMMITTED。

第二次,COM+ 到 .NET 互操作条件导致数据库连接默认为 SERIALIZABLE。

对我们来说,一个快速而肮脏的解决方案是在 SQL 命令前加上“SET TRANSACTION ISOLATION LEVEL READ COMMITTED”来覆盖 SERIALIZABLE,直到核心问题得到解决。

于 2009-11-11T17:11:22.450 回答
0

罪魁祸首似乎是:-

owner id="processb855b8" mode="RangeS-U"

这似乎锁定了一组行。它正在等待 process84af28 释放一行,它正在等待 processb852e8 释放一行,而 processb852e8 正在等待第一个进程释放一行。

SQLServer 正在通过终止中间进程允许其他两个进程完成来解决死锁。

您应该查看您的隔离级别。最佳做法是在“选择”多行时使用最低可用级别的锁定。如果您很可能更新当前事务中的行,则仅在“选定”行上使用更高级别。

并且永远不要在等待外部服务或用户操作时锁定一行。

于 2009-11-11T01:44:12.833 回答