2009-09-17 3 views
5

У меня проблема с блокировкой с двумя транзакциями, которые не имеют доступа к каким-либо общим записям. Также не существует эскалации блокировки. Поэтому я не могу объяснить, почему возможен тупик.SqlServer 2005: проблема взаимоблокировки без общих записей

Тупик возникает, когда два таких операций выполняются одновременно:

begin transaction 

update A set [value] = [value] 
where id = 1; /* resp. 2 */ 

/* synchronize transactions here */ 

SELECT * 
FROM 
A inner join B on A.B_FK = B.id 
inner join C on C.A_FK = A.id 
WHERE 
A.[value] = 1; /* resp. 2 */ 

rollback; 

Эти таблицы и данные для настройки сценария:

CREATE TABLE A (
    id INT NOT NULL, 
    [value] INT, 
    B_FK INT 
    primary key (id) 
) 

CREATE TABLE B (
    id INT NOT NULL, 
    primary key (id) 
) 

CREATE TABLE C (
    id INT NOT NULL, 
    A_FK INT 
    primary key (id) 
) 

INSERT INTO A VALUES(1, 1, 1) 
INSERT INTO B VALUES(1) 
INSERT INTO C VALUES(1, 1) 

INSERT INTO A VALUES(2, 2, 2) 
INSERT INTO B VALUES(2) 
INSERT INTO C VALUES(2, 2) 

Таблица A находится в середине три таблицы. Если я изменю что-либо в запросе, например, удалите одну из объединенных таблиц B или C, нет тупика. То же самое, когда я фильтрую на A.id вместо A.value.

График взаимоблокировки говорит мне, что они оба хотят установить блокировку S на индекс первичного ключа таблицы A. Опять же: эскалации блокировки нет.

Я использую SqlServer 2005.

  • Почему эти сделки противоречат друг другу без доступа к любым общим данным? Может кто-нибудь объяснить это?
  • Что можно сделать, чтобы избежать этого? Я использую NHibernate и не могу легко изменить запрос.
  • Может быть проблема с SqlServer?

Большое спасибо.

+0

что делать "/ * синхронизация сделка здесь * /" означает? –

+0

@Mitch: Это означает, что я выполняю транзакцию 1 до этой точки, затем выполняю транзакцию 2, которая ждет выбора, затем я запускаю транзакцию 1 до конца, которая также ждет выбора. –

ответ

7

Конфликт может произойти, поскольку SQL-сервер блокирует не только уровень строки, но также и на уровне страницы или даже на уровне таблицы.

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

SQL Server Lock Contention Tamed может быть полезным

+0

Да - если он не может получить блокировку на уровне строк, он перерастает на страницу, а затем на таблицу. – 2009-09-17 07:37:34

+0

Но разве это не эскалация блокировки? Не следует ли проследить его в профилировщике? –

+0

С моей точки зрения сервер Sql может решить использовать блокировку страницы с самого начала. В этом случае эскалации не будет. – Wolfgang

1

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

+0

К счастью, у меня нет триггеров в db. Спасибо, в любом случае. –

+0

Не могли бы вы рассказать о том, почему триггеры имеют какое-то значение? –