为什么在SQL Server中发生死锁?

tsi*_*ilb 9 sql sql-server deadlock

据我所知,当SPID忙于处理另一个查询时会发生SQL死锁,而且由于它现在非常繁忙而无法再运行另一个查询.SQL Server"随机"选择其中一个查询从请求的资源中解锁,并将其取消,抛出异常.

我有一个应用程序运行~40个实例和一个后端Windows服务,所有这些都在同一个数据库中.我希望减少死锁,这样我就可以增加可以同时运行的线程数.

  1. 为什么SQL Server不能将新查询排入队列并在有时间并且资源可用时运行它?我正在做的大部分时间可能会等待几秒钟.
  2. 有没有办法全局设置事务隔离级别,而无需在每个新连接/会话开始时指定它?

Tom*_*m H 20

您对死锁的理解不正确.你所描述的是封锁.将两者等同起来是一个常见的错误.

当两个单独的事务每个都需要不同的资源时,就会发生死锁,并且它们都不会释放它们拥有的那个以便另一个可以运行.它可能更容易说明:

SPID#1获取资源锁定SPID#2获取资源B锁定SPID#1现在需要锁定资源B才能完成SPID#2现在需要锁定资源A才能完成

SPID#1无法完成(因此释放资源A),因为SPID#2有SPID#2无法完成(因此发布资源B),因为SPID#1有它

由于SPID都不能完成,因此必须放弃(即由服务器选择作为死锁受害者)并且将失败.

避免它们的最佳方法是保持交易量小(需要的资源数量)并且快速.

  • (+1)想象一下,两条车在单车道道路上朝向彼此.他们都需要继续前行,但显然他们都不能拥有它,除非一辆车倒车或消失(即"回滚").没有多少等待,内存,磁盘等可以提供帮助 (5认同)
  • @tsilb这个问题比乍看之下要复杂得多。正如汤姆·H(Tom H.)所建议的那样,您可能想要搜索死锁以及“隔离级别”。简而言之,您不能告诉它不要对更改数据的命令进行锁定,但是可以在读取操作中告诉它使用“ With NOLOCK”查询提示来读取锁定。但这附带了风险,应非常小心地使用。 (2认同)