我想知道,由于行锁的增加,和/或因为持有锁的时间增加,在一个表上定义一个复合主键是否会增加在同时更新我的多个线程时出现死锁的可能性?
谢谢你的帮助。
发布于 2012-10-16 21:38:53
如果您正在使用复合PKs,并且正在并行插入大量数据,则可能会受到资源散列冲突的影响。有关真实世界的示例,请参阅"The Curious Case of the Dubious Deadlock and the Not So Logical Lock"。
对于资源散列冲突的解释,我将引用"%%lockres%% collision probability magic marker: 16,777,215"中的Remus Rusanu (推荐阅读):
SQL Server中的锁管理器
不知道它锁定的是什么,它只锁定“资源”(基本上是字符串)。它是更高级别组件的工作,比如存储引擎的访问方法,将“资源”呈现给锁管理器并请求所需的锁。当锁定堆或b树中的行时,存储引擎将从记录标识符合成为“资源”。由于这些资源具有有限的长度,因此存储引擎必须将密钥的有效长度减少到允许呈现给锁管理器的最大长度,这意味着记录的密钥将减少到6个字节。这是通过将密钥散列为6字节的散列值来实现的。
..。
在6个字节上有281,474,976,710,656个不同的可能值。这是一个相当大的数字?实际上并不是很大。..。因此,SQL%%lockres%%散列将产生两个具有相同散列的记录,并且只有16,777,215条记录存在于表之外,任何表中的概率为50%。
发布于 2012-10-16 23:49:25
由于SQL Server的Lock Manager使用了一个lockhash值(而不是直接使用PK ),因此我可以得出结论,使用单列PK锁定与使用复合PK锁定没有区别。
Improvement in minimizing lockhash key collisions in SQL Server 2008R2 and its impact on concurrency
与其他一些数据库供应商不同的是,SQL Server的锁管理器有一个逻辑组件。SQL Server使用锁散列值来表示SQL Server锁管理器中的锁结构上的锁,而不是使用行、页或表的物理说明。然后将锁散列值保存在内存中。
我的结论是,与复合键相比,从单个列键获得锁散列值的散列冲突的可能性不会更大。正如SQL 2008R2的链接所示,锁散列得到了显着改进,并专门解决了组合键的问题。
在2008R2之前,lockhash对于单个密钥和复合密钥都不是很完美。
保持PK简短是一种很好的做法。
.NET KeyValuePair和元组不会生成良好的哈希。
发布于 2012-10-16 21:20:33
一般来说,我倾向于说不,它不是设计良好的代码。原因是死锁的原因和避免/消除它们的技术通常与时间无关。大多数死锁的发生是因为线程中的更新路径不同。例如,代码A先更新Table1,然后更新Table2,而代码块B先更新Table2,然后更新Table1。避免这种情况的技术涉及到确保各个代码块尝试并以相同的顺序更新项目。换句话说,避免这样的场景:线程1在A上有一个锁并希望更新B,而线程2在B上有一个锁并想要更新A。
但是,如果存在这些冲突的编码块/语句,我认为组合键会增加死锁发生的频率。基本上,一个事务完成的时间越长,另一个线程锁定其他资源并导致死锁的时间就越长。
除了一个非常小的/特定的边缘情况,我不认为组合键会对死锁的发生产生影响(至少在我的经验中不会)。
https://stackoverflow.com/questions/12915480
复制相似问题