SQL事务死锁了。

32

有时在不是非常繁忙的 SQL 服务器上,我会遇到这种异常:

Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
Line number: 1
Error Number: 1205
Procedure: 
Server name: P01
Error Source: .Net SqlClient Data Provider
Error State: 47
我无法重现这个问题。我尝试从不同的客户端同时运行多个查询,但它没有出现。 当存储过程或触发器内发生这种问题时,最好的处理方式是什么?我的意思是,如何重新运行事务? 当触发器调用的过程中发生异常,该过程又由某个过程进行插入时,该如何处理? (即: procedure01 -> insert -> trigger -> procedure02 !)
4个回答

42

我建议您从两个角度来解决这个问题。

  1. 捕获 死锁错误,以便您可以重新运行被 SQL Server 数据库引擎选择为死锁受害者的事务。

  2. 找出是什么导致了您的死锁事件。您可以通过以下两种方式之一来实现:运行SQL Server Profiler Trace以捕获和记录死锁事件,或者启用一些SQL Server Trace Flags,将死锁事件的详细信息记录到 SQL Server 错误日志中。

绝大多数情况下,您可以通过对数据库架构进行结构性更改或对涉及/负责死锁事件的代码进行逻辑更改来确定死锁事件的原因并解决问题。

如需进一步阅读,请参阅:

我希望我已经回答了您的问题,但如果有任何进一步的帮助,请告诉我。


什么导致了你的死锁事件?并非性能下降。 - Kiquenet
2
如果能提供一些通常导致错误的提示,这个答案会更有帮助。是我的应用程序代码出了问题?SQL存储过程有误?还是MSSQL存在漏洞? - Tomáš Zato

5

设置一个服务器端SQL跟踪,以捕获死锁图事件,这样您就可以使用SQL Profiler查看.trc文件。 这样,您就有了一些东西来解决任何死锁问题。 我提供了以下代码。 您需要根据需要更改文件路径。 最好将此脚本配置为在SQL服务器启动时执行。

FYI-死锁可能由很多不同的因素引起,其中之一是缺少索引。

declare @rc int
declare @TraceID int
declare @maxfilesize bigint
set @maxfilesize = 10 
declare @dtName nvarchar(50)
select @dtName=(N'I:\Trace_Logs\DeadLockTrace'+ convert(nvarchar(8),getdate(),112))


-- Please replace the text InsertFileNameHere, with an appropriate
-- filename prefixed by a path, e.g., c:\MyFolder\MyTrace. The .trc extension
-- will be appended to the filename automatically. If you are writing from
-- remote server to local drive, please use UNC path and make sure server has
-- write access to your network share

exec @rc = sp_trace_create @TraceID output, 2, @dtName, @maxfilesize, NULL ,365

if (@rc != 0) goto error

-- Client side File and Table cannot be scripted

-- Set the events
declare @on bit
set @on = 1
exec sp_trace_setevent @TraceID, 148, 11, @on
exec sp_trace_setevent @TraceID, 148, 51, @on
exec sp_trace_setevent @TraceID, 148, 4, @on
exec sp_trace_setevent @TraceID, 148, 12, @on
exec sp_trace_setevent @TraceID, 148, 14, @on
exec sp_trace_setevent @TraceID, 148, 26, @on
exec sp_trace_setevent @TraceID, 148, 60, @on
exec sp_trace_setevent @TraceID, 148, 64, @on
exec sp_trace_setevent @TraceID, 148, 1, @on
exec sp_trace_setevent @TraceID, 148, 41, @on
exec sp_trace_setevent @TraceID, 25, 7, @on
exec sp_trace_setevent @TraceID, 25, 15, @on
exec sp_trace_setevent @TraceID, 25, 55, @on
exec sp_trace_setevent @TraceID, 25, 8, @on
exec sp_trace_setevent @TraceID, 25, 32, @on
exec sp_trace_setevent @TraceID, 25, 56, @on
exec sp_trace_setevent @TraceID, 25, 64, @on
exec sp_trace_setevent @TraceID, 25, 1, @on
exec sp_trace_setevent @TraceID, 25, 9, @on
exec sp_trace_setevent @TraceID, 25, 25, @on
exec sp_trace_setevent @TraceID, 25, 41, @on
exec sp_trace_setevent @TraceID, 25, 49, @on
exec sp_trace_setevent @TraceID, 25, 57, @on
exec sp_trace_setevent @TraceID, 25, 2, @on
exec sp_trace_setevent @TraceID, 25, 10, @on
exec sp_trace_setevent @TraceID, 25, 26, @on
exec sp_trace_setevent @TraceID, 25, 58, @on
exec sp_trace_setevent @TraceID, 25, 3, @on
exec sp_trace_setevent @TraceID, 25, 11, @on
exec sp_trace_setevent @TraceID, 25, 35, @on
exec sp_trace_setevent @TraceID, 25, 51, @on
exec sp_trace_setevent @TraceID, 25, 4, @on
exec sp_trace_setevent @TraceID, 25, 12, @on
exec sp_trace_setevent @TraceID, 25, 52, @on
exec sp_trace_setevent @TraceID, 25, 60, @on
exec sp_trace_setevent @TraceID, 25, 13, @on
exec sp_trace_setevent @TraceID, 25, 6, @on
exec sp_trace_setevent @TraceID, 25, 14, @on
exec sp_trace_setevent @TraceID, 25, 22, @on
exec sp_trace_setevent @TraceID, 59, 55, @on
exec sp_trace_setevent @TraceID, 59, 32, @on
exec sp_trace_setevent @TraceID, 59, 56, @on
exec sp_trace_setevent @TraceID, 59, 64, @on
exec sp_trace_setevent @TraceID, 59, 1, @on
exec sp_trace_setevent @TraceID, 59, 21, @on
exec sp_trace_setevent @TraceID, 59, 25, @on
exec sp_trace_setevent @TraceID, 59, 41, @on
exec sp_trace_setevent @TraceID, 59, 49, @on
exec sp_trace_setevent @TraceID, 59, 57, @on
exec sp_trace_setevent @TraceID, 59, 2, @on
exec sp_trace_setevent @TraceID, 59, 14, @on
exec sp_trace_setevent @TraceID, 59, 22, @on
exec sp_trace_setevent @TraceID, 59, 26, @on
exec sp_trace_setevent @TraceID, 59, 58, @on
exec sp_trace_setevent @TraceID, 59, 3, @on
exec sp_trace_setevent @TraceID, 59, 35, @on
exec sp_trace_setevent @TraceID, 59, 51, @on
exec sp_trace_setevent @TraceID, 59, 4, @on
exec sp_trace_setevent @TraceID, 59, 12, @on
exec sp_trace_setevent @TraceID, 59, 52, @on
exec sp_trace_setevent @TraceID, 59, 60, @on

-- Set the Filters
declare @intfilter int
declare @bigintfilter bigint

-- Set the trace status to start
exec sp_trace_setstatus @TraceID, 1

-- display trace id for future references
select TraceID=@TraceID
goto finish

error: 
select ErrorCode=@rc

finish: 
go

在我的情况下,缺少索引导致了死锁。 - singhswat
如何使用 UNC 路径? - Drewdin

2

我使用ReadCommited隔离级别解决了类似的问题。


0

我通过以下步骤解决了这个错误:

  1. 重新启动SQL Server
  2. 运行查询:

    USE [master] ALTER DATABASE name_database SET MULTI_USER WITH ROLLBACK IMMEDIATE

祝你好运!


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