Подтвердить что ты не робот

SQL-транзакция зашла в тупик

Иногда я получаю такое исключение на не очень занятом 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!)

4b9b3361

Ответ 1

Я бы предположил, что вы столкнулись с проблемой с двух сторон.

  • Trap или Catch Ошибки Deadlock, чтобы вы могли повторно запустить транзакцию, выбранную как жертва Deadlock с помощью SQL Server базы данных.

  • Узнайте, что вызывает ваши события Deadlock. Вы можете сделать это одним из двух способов: либо запустить трассировку профилей SQL Server, чтобы поймать и записать событие Deadlock, либо вы можете включить некоторые флаги трассировки SQL Server, который будет записывать сведения о событии Deadlock в журнал ошибок SQL Server.

В случаях подавляющее большинство вы можете определить причину своих событий Deadlock и исправить ситуацию либо структурным изменением схемы базы данных, либо логическим изменением кода, связанного/ответственного за Событие взаимоблокировки.

Для дальнейшего чтения посмотрите:

Надеюсь, я ответил на ваш вопрос, но дайте мне знать, если я могу помочь вам в дальнейшем.

Ответ 2

Настройте SQL-трассировку на стороне сервера, которая фиксирует события тупикового графика, чтобы вы могли посмотреть файл .trc с помощью SQL Profiler. Таким образом, вы можете иметь что-то на месте, чтобы иметь возможность устранить любой тупик. Я предоставил код ниже. Вам необходимо будет изменить путь к файлу. Было бы неплохо настроить этот script для запуска при запуске 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 [email protected]
goto finish

error: 
select [email protected]

finish: 
go

Ответ 3

Я решил проблему с использованием уровня изоляции ReadCommited.