sar*_*off 1 sql-server deadlock parallelism transaction
首先 1 个线程从表中选择大量数据。
然后,在 SELECT 查询尚未完成之前,另一个线程从该表中删除数据。
它导致 SELECT 查询失败,错误 errorCode=1205 sqlState=40001 和发生死锁的消息。
我认为第二个事务必须等到第一个事务完成,或者第一个事务必须在没有第二个事务所做更改的情况下返回数据。我怎样才能避免这种情况?
我无法改变交易的顺序或以某种方式控制它们(应用程序的用户很多,他们可以随时以任何顺序做任何他们想做的事情)。为什么会发生?
查询是这样的(我对它们进行了一些混淆):
SELECT distinct P.pID, (LastNAME+' '+FirstName+' '+SurName) as NAME, 'person' as Type, CA.OrgName, PC.personemail as Email
FROM Persons P
INNER JOIN WORK PW ON (P.mainwork = PW.pwId)
INNER JOIN CONTACT PC ON (PC.pID = P.pID)
LEFT OUTER JOIN ORG CA ON (CA.orgId = PW.orgId)
WHERE (P.Status = ?)
Run Code Online (Sandbox Code Playgroud)
和
DELETE FROM persons WHERE id = 1234
Run Code Online (Sandbox Code Playgroud)
我认为第二笔交易必须等到第一笔交易完成
基本上,这不是真的。如果一次只有一个人可以用它做某事,那么您(或任何人)的数据库将不会非常有效。
为什么会发生?
简单地:
SELECT 查询在它所查看的任何行上都使用共享锁,因此尽管它不会与另一个 SELECT 查询发生冲突,但它肯定会与来自 DELETE 的排他锁发生冲突。由于 SELECT 查询不会更新任何内容,因此它通常会成为死锁的受害者,因为它可能是回滚成本最低的。
如果没有进一步的信息,就不可能说在你所谈论的情况下为什么会发生这种情况。我会在最后添加一些死锁检测链接,但我怀疑这不是问题的主要目的,所以......
该怎么办?
很难知道哪种方法最适合您(没有更多信息)。您可能应该查看一下您的隔离级别。
您可以使用 READ_COMMITTED_SNAPSHOT,但这可能会导致进一步的开销,或者使用 READ_UNCOMMITED/使用 NOLOCK 提示 - 我通常不喜欢这些选项,因为返回的数据实际上可能不是您想要的,但它们可能适用于你的情况。很难确切地说什么是最好的,因为它取决于有关您的系统及其用途的许多不同变量。
在这方面你可以做的最好的事情是阅读隔离级别,这些是一些类似的帖子/来源,可以让你开始并更详细地讨论事情。
MSDN - 选择语句如何导致被选为死锁受害者?, SQL Server 中心, MSDN - 了解隔离级别
但...
不要急于进行更改,只是为了完成查询。更合适的探索途径可能是您的查询本身。
为什么 SELECT 语句需要这么长时间才能运行?为什么从表中删除的东西如此频繁?也许一些简单的查询调整会让它们更快地完成并减少死锁的机会。也许您需要对您的数据库服务器进行一些常规的性能调整(我不会在这里详细讨论这个问题,因为它已经偏离主题了)。
您必须确保您的查询适合业务目的,而不是查询只是“不惜一切代价完成”,数据库首先是一个业务工具,需要解决这个问题(无论我们有多不喜欢)!
只是继续更改隔离级别,甚至只是使用 NOLOCK,都会对您的数据库以及查询返回的确切结果产生重大影响 - 这可能会对业务产生影响。
还...
为了帮助检测死锁,请查看StackOverflow上的这篇文章并查看MSDN 站点上的死锁信息工具,该工具将解释如何使用跟踪标志来提供有关死锁的更多信息。
最后...
如果您将 SQL Server 版本放在您的帖子中,则可以提供更具体的建议,以及有关 SELECT 查询究竟是什么的更多详细信息(查看是否有任何可能导致它花费这么长时间并因锁定而打开) .
| 归档时间: |
|
| 查看次数: |
7710 次 |
| 最近记录: |