Хранимая блокировка транзакции в SQL Server 2005 - PullRequest
0 голосов
/ 18 февраля 2011

У меня проблема при запуске хранимой процедуры sql (MSSQL 2005).Вот его код:

CREATE PROCEDURE [GetItemColors]
    @FetchCount int
AS
BEGIN
SELECT 
    TOP (@FetchCount) item.Id as ItemId, item.Published as Published, attributeValue.String as Color
    FROM tblItem item, tblAttribute attributeValue, tblAttributeDefinition attributeDef
    WHERE 
        item.Id = attributeValue.fkItemId 
        AND item.Deleted = 0
        AND item.PendingPublish = 0 
        AND attributeValue.fkAttributeDefinitionId = attributeDef.Id
        AND attributeDef.[Name] = 'Color'
    ORDER BY item.Published DESC
END;

Иногда выполнение процедуры заканчивается с исключением:

SqlException: Transaction (Process ID 66) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

Кто-нибудь знает, как переписать процедуру, чтобы избежать исключения?

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

Заранее спасибо за помощь!


правка 1: примерный план выполнения прилагается

estimated execution plan


правка 2: я не могу получить график тупиков, поскольку исключение происходит пару раздень только в живой среде.Мне не разрешено запускать профилировщик в живом окружении.Мне не удалось воспроизвести тупик в среде разработки.


edit 3: Мне не удалось получить победителя тупика.

1 Ответ

3 голосов
/ 18 февраля 2011
  1. опубликовать информацию о взаимоблокировке.См. Как: сохранить графики взаимоблокировок .
  2. опубликовать оператор, эта процедура зашла в тупик с (т. Е. Победителем тупика)
  3. опубликовать точная схема ваших задействованных таблиц, включая все индексы, кластеризованные и некластеризованные

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

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

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

Что касается магии 'Стратегия предварительной блокировки, вы можете взять кувалду и украсить свой запрос или подсказками TABLOCK, или даже TABLOCKX, но производительность быстро снизится.Надлежащее решение - устранить тупик, а не форсировать сериализацию.

...