表锁抛出异常 vs 表锁等待结束

4

我现在想知道为什么有时候当表被锁住时,ADO.NET 会直接抛出表锁定异常,而有时候执行的语句会等待,直到表不再被锁住。什么情况下表锁会引起异常,什么情况下不会?很遗憾我没有代码来重现这两种情况。

Sybase SQL 中是否有任何规则来说明这种行为呢?

谢谢大家!


我们是在谈论并发异常、死锁还是其他什么? - mybirthname
谢谢您的回复 :) 我们正在讨论并发异常。 - BendEg
3
这里有一篇关于锁定的文章:http://www.codeproject.com/Articles/114262/ways-of-doing-locking-in-NET-Pessimistic-and-opt#Solution%20number%202:-%20Use%20timestamp%20data%20type ,个人偏爱使用时间戳方式,这在第二点中有解释。 - mybirthname
我不是Sybase用户,但通常数据库服务器会等待获取锁定直到连接超时。死锁情况,即用户A想要访问B已经锁定的资源,而B正在等待A已经锁定的资源,可以被检测到并选择其中一个作为牺牲品。牺牲者的事务将被回滚,另一个事务将继续执行。无论等待多长时间,死锁都不会自行解决,因此在这种情况下牺牲者始终会收到异常信息。 - John D
1个回答

1
Sybase和MsSql共享相同的历史代码库。在早期(SQL 2000之前)以及同一时代的Sybase中,两个供应商都没有解决他们的锁定问题。它们都可能陷入死锁状态。问题出在它们使用的逻辑上。想象一下死锁情况就像在十字路口开车。假设规则是当两条记录(汽车)同时到达时向右让行。这在只有两辆车时运行良好,但当四辆车同时到达并试图让右侧的车道时,您会遇到死锁情况。早年间,数据库管理员需要选择一条记录来终止该事务(阻塞其完成),以允许死锁清除。后来,MsSql实现了逻辑,可以自动选择要终止的记录。他们还改进了他们的锁定逻辑,因此未来版本中死锁发生的频率要少得多。所以有时它起作用,有时它不起作用,取决于您的记录是否被选择为要终止或其他死锁是否完成,从而允许处理您的记录。
Oracle的锁定逻辑更好。他们根据多个进程同时修改某个字段的情况保留多个副本。当您执行选择时,您会得到已提交的记录,而不是Sybase/MsSql锁定方案等待完成的长时间运行的不完整进程。稍后的MsSql版本比Sql 7和sql 2000做得更好,在那里它是一个更大的问题。Sybase可能经历了同样的改进。
有方法可以通过将大表拆分成较小的表并分批从较小的表更新到较大的表来减少此锁定问题。将其视为左右表。当您将高容量插入到活动的左表中时,右表正在插入到主表中。然后您切换并在左表移动到主表时对右表进行高容量插入。这将事务分解为表之间,并减少多个进程同时访问同一表的机会(减少死锁)。但是这意味着您没有最新的数据,因为您的左侧和右侧表中有未完全处理的记录。

忘了提一句。Dot net还允许您对数据库做各种恶心的事情,包括在使用dot net代码集进行处理时锁定表格。这是一个关于锁定问题的恐怖故事。永远不要使用这些选项。当您遇到锁定问题时,请尝试移除所有脚本kiddy dot net代码。让您的dot net开发人员专门与存储过程交互。这将极大地减少死锁问题。 - M T Head

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