![]() |
1
9
最好是自动重试死锁。原因是你可以解决 这 死锁,后来又撞了一个。如果表的大小改变了,如果服务器硬件规范改变了,即使服务器上的负载改变了,sql版本之间的行为也可能改变。如果死锁很频繁,您应该采取主动措施消除它(索引通常是答案),但是对于罕见的死锁(比如每10分钟左右),应用程序中的重试可以掩盖死锁。您可以重试读取 或 写操作,因为写操作当然被适当的begin transaction/commit事务包围,以保持所有写操作是原子的,因此能够在没有问题的情况下重试它们。 另一个考虑的途径是 read committed snapshot . 启用此选项后,select将不接受任何锁,但会产生一致的读取。 |
![]() |
2
5
为了避免死锁,最常见的建议之一是“以相同的顺序获取锁”或“以相同的顺序访问对象”。显然这是完全有道理的,但它总是可行的吗?总有可能吗?当我不能遵循这个建议时,我总是遇到一些情况。 如果我将一个对象存储在一个父表和一个或多个子表中,我就完全不能遵循这个建议。插入时,我需要先插入父行。删除时,我必须按相反的顺序执行。 如果我使用的命令涉及一个表中的多个表或多行,那么通常我无法控制获取锁的顺序(假设我没有使用提示)。 因此,在许多情况下,试图以相同的顺序获取锁并不能防止所有死锁。所以,无论如何,我们需要某种处理死锁的方法——我们不能假设我们能全部消除它们。 当然,除非我们使用service broker或sp_getapplock序列化所有访问。 当我们在死锁后重试时,很可能会覆盖其他进程的更改。我们需要知道,很可能是其他人修改了我们打算修改的数据。特别是如果所有读卡器都在快照隔离下运行,那么读卡器就不能参与死锁,这意味着死锁中涉及的所有方都是编写器、修改或试图修改同一数据。如果我们只捕获异常并自动重试,则可以覆盖其他人的更改。 这称为丢失更新,通常是错误的。通常,在死锁之后正确的做法是在更高的级别上重试-重新选择数据并决定是否以与原始保存决定相同的方式保存。 例如,如果用户按下save按钮,而saving事务被选为死锁牺牲品,那么最好在死锁之后在屏幕上重新显示数据。 |
![]() |
3
2
捕获和重新运行可以工作,但是您确定select始终是死锁的牺牲品吗?如果插入是死锁的牺牲品,则必须更加小心地重试。 我认为,在这种情况下,最简单的解决方案是取消锁定或重新未提交(同样的事情)您的选择。人们有理由担心脏读,但多年来,为了获得更高的并发性,我们到处运行nolock,从来没有遇到过问题。 我还将对锁语义做更多的研究。例如,我相信如果将事务隔离级别设置为snapshot(需要2005或更高版本),问题就会消失。 |
![]() |
Duvan · 将逗号(,)替换为点(.)[副本] 2 年前 |
![]() |
Mateen Bagheri · 选择表的计数并选择其自身 2 年前 |
![]() |
SoT · SQL Server中求和函数的工作方式 2 年前 |
![]() |
NKAT · 将列值聚合到列表中会产生错误 2 年前 |
![]() |
deanpillow · 返回两列中有一个匹配值的记录 2 年前 |
![]() |
snowflakes74 · 在Dapper中异步查询多个结果 2 年前 |