Проблема тупика SQL Server - PullRequest
0 голосов
/ 01 июня 2010

Я использую SQL Server 2008 Enterprise. Мне интересно, вызвана ли проблема мертвой блокировки только взаимными зависимостями (например, задача A имеет блокировку на L1, но ожидает блокировки на L2, и в то же время задача B имеет блокировку на L2, но ожидает блокировки на L1)? Существуют ли другие причины и сценарии, которые могут привести к тупику?

Существуют ли другие способы, которые могут привести к блокировке - например, тайм-аут (оператор S / I / D / U не возвращается в течение очень долгого времени, и будет возвращена ошибка взаимоблокировки) или не может получить блокировку в течение длительного времени, но не вызван перекрестными зависимостями (например, задача C должна получить блокировка таблицы T, но другая задача D получает блокировку таблицы T без снятия блокировки, что приводит к тому, что задача C не может получить блокировку таблицы T в течение длительного времени)?

РЕДАКТИРОВАТЬ 1: вызовет ли эта процедура сохранения взаимоблокировку, если она выполняется несколькими потоками одновременно?

create PROCEDURE [dbo].[FooProc]    
(  
 @Param1 int 
 ,@Param2 int  
 ,@Param3 int  
)    
AS    

DELETE FooTable WHERE  Param1 = @Param1     

INSERT INTO FooTable    
 (  
 Param1  
 ,Param2  
 ,Param3  
  )    
 VALUES    
 (  
 @Param1  
 ,@Param2  
 ,@Param3  
  )    

DECLARE @ID bigint    
 SET @ID = ISNULL(@@Identity,-1)    
 IF @ID > 0    
 BEGIN    
      SELECT IdentityStr FROM FooTable WHERE ID = @ID 
 END  

спасибо заранее, George

Ответы [ 3 ]

2 голосов
/ 01 июня 2010

В случае взаимных блокировок требуется цикл, когда ресурсы блокируются процессами, которые ожидают блокировки, удерживаемые другими процессами, чтобы снять блокировки. Любое количество процессов может участвовать в взаимоблокировке, и обычный метод обнаружения взаимоблокировок - это взять график зависимостей от блокировок и найти циклы в этом графе.

Вам нужен этот цикл, чтобы существовал тупик. Все остальное - это просто процесс, задержанный в ожидании снятия блокировки. Sp_who2 - быстрый способ узнать, какие процессы блокируются другими.

Если вы хотите устранить неполадки взаимоблокировки, лучше всего запустить трассировку, собирая события «графика взаимоблокировок». Это позволит вам увидеть, что происходит, сообщив, какие запросы удерживают блокировки.

2 голосов
/ 01 июня 2010

Также существуют тупики преобразования: оба процесса A и B имеют общие блокировки на ресурсе C. Оба хотят получить эксклюзивные блокировки на C.

Даже если два процесса конкурируют только на одном ресурсе, они все равно могут оказаться в тупике. Следующие сценарии воспроизводят такой сценарий. В одной вкладке запустите это:

CREATE TABLE dbo.Test ( i INT ) ;
GO
INSERT  INTO dbo.Test
        ( i )
VALUES  ( 1 ) ;
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
BEGIN TRAN
SELECT  i
FROM    dbo.Test ;

--UPDATE dbo.Test SET i=2 ;

После завершения этого скрипта у нас есть ожидающая транзакция с общей блокировкой. На другой вкладке давайте представим, что другое соединение имеет общую блокировку на том же ресурсе:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
BEGIN TRAN
SELECT  i
FROM    dbo.Test ;

--UPDATE dbo.Test SET i=2 ;

Этот скрипт завершает и отображает набор результатов, как и первый скрипт. Теперь давайте выделим и выполним комментируемые команды обновления на обеих вкладках. Для выполнения обновления каждому соединению требуется эксклюзивная блокировка. Ни одно соединение не может получить эту эксклюзивную блокировку, потому что другое удерживает общую блокировку. Хотя оба соединения конкурируют только на одном ресурсе, они оказались в тупике конверсии:

Сообщение 1205, Уровень 13, Состояние 56, Строка 1 Транзакция (ID процесса 59) была заблокирована для ресурсов блокировки с другим процессом и была выбрана в качестве жертвы тупика. Перезапустите транзакцию.

Также обратите внимание, что более двух соединений могут оказаться в тупике.

0 голосов
/ 01 июня 2010

Просто не снимать блокировку долгое время - это не тупик.

Тупик - это ситуация, когда вы никогда не сможете идти вперед. Это вызвано 2 (или более) процессами, которые ожидают завершения других, но все участвующие удерживают блокировку, которая препятствует продолжению других (ей).

Единственный выход из тупика - это убить процессы, чтобы освободить блокировки, так как не имеет значения, как долго вы ждете, он не может завершить сам по себе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...