[英]Database Locking Problem
请 我们已经在生产数据库上获得了很多锁,最近见证了流量的大幅增加。 我们将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,但此跟踪似乎表明:
子表中的行上具有排他锁X的进程正在尝试获取同一资源上的Select-Update锁(似乎没有道理)
具有Select-Update锁定的另一个进程仍在尝试获取Select-Update锁定
澄清有人吗?
我们如何最小化或消除僵局?
首先要注意的几件事:
您正在使用可序列化事务 ,这是最严格的悲观锁定形式。 可能是不需要的(我们知道您正在使用可序列化的事务,因为KEY锁定仅适用于此隔离级别)。 正如Remus在上面提到的,您绝对应该在这里最有可能研究其他选项。
似乎上面的输出已被截断了一点,您应该有一个名为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部分 。 您还可以在此处大致了解并发和脚本概述。
mode="RangeS-U"
范围锁? 停止使用较高的事务隔离级别。 坚持阅读提交。 如果使用CLR TransactionScope对象,则使它们使用Read Commited隔离(默认情况下,它们使用Seralizable,yuck)。 尝试打开数据库上的已读提交快照隔离。 请参阅使用快照隔离 。
罪魁祸首似乎是:
owner id="processb855b8" mode="RangeS-U"
这似乎已经锁定了一组行。 它的等待行由process84af28实现,它正在等待行由processb852e8实现,该进程正在等待第一个进程释放一行。
SQLServer通过杀死中间的进程以允许其他两个进程完成来解决死锁。
您应该查看隔离级别。 最佳实践是在“选择”多行时使用最低的可用锁定级别。 如果您很有可能在当前事务中更新该行,则仅在“选定”行上使用更高级别。
而且,永远不要在等待外部服务或用户操作时将行锁定。
我自己用其他产品(不是IdeaBlade)看到了这个死锁问题。 以我的经验,这不是数据库问题。 软件与数据库通信可能是一个问题。
我的问题是与数据库通信的组件的配置。
第一次,COM +默认为SERIALIZABLE,并且必须配置为默认为READ COMMITTED。
第二次,从COM +到.NET互操作的情况,导致数据库连接默认为SERIALIZABLE。
对于我们来说,一种快速而又肮脏的解决方案是在SQL命令之前加上“ SET TRANSACTION ISOLATION LEVEL READ COMMITTED”,以覆盖SERIALIZABLE,直到可以解决核心问题为止。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.