У меня есть хранимая процедура со следующими заявлениями в немМертвого замка даже после добавления индекса
INSERT INTO dbo.[ResultItems] (PGM,GRP,PGMGRPSEQ,ITMID,ITMDESC,BRAND,PackSize,IsSelected,UserId)
SELECT SRIS.PGM,SRIS.GRP,SRIS.PGMGRPSEQ,SRIS.ITMID,SRIS.ITMDESC,SRIS.BRAND,SRIS.PackSize,SRIS.IsSelected,SRIS.UserId
FROM @ItemResult SRIS
LEFT OUTER JOIN [dbo].[ResultItems] SRI (NOLOCK)
ON SRI.ITMID = SRIS.ITMID
AND SRI.PGM = SRIS.PGM
AND SRI.GRP = SRIS.GRP
AND SRI.PGMGRPSEQ = SRIS.PGMGRPSEQ
AND SRI.UserId=SRIS.UserId
WHERE SRI.ITMID IS NULL ----logic to avoid duplicate
GROUP BY SRIS.PGM,SRIS.GRP,SRIS.PGMGRPSEQ,SRIS.ITMID,SRIS.ITMDESC,SRIS.BRAND,SRIS.PackSize,SRIS.IsSelected,SRIS.UserId
UPDATE SRI
SET SRI.IsSelected = 1
FROM @ItemResult IST
INNER JOIN [dbo].ResultItems SRI (NOLOCK)
ON SRI.PGM = IST.[PGM]
AND SRI.GRP = IST.GRP
AND SRI.PGMGRPSEQ = IST.PGMGRPSEQ
AND SRI.ITMID = IST.ITMID
AND SRI.UserId=IST.UserId
WHERE [email protected]
Я следующий index
на столе ResultItems
IF NOT EXISTS(select 1 from sys.sysindexes where name = 'IX_RESULTITEMS_USERID')
BEGIN
CREATE NONCLUSTERED INDEX IX_RESULTITEMS_USERID
ON [dbo].[ResultItems] ([UserId])
END
GO
Пяти одновременных пользователи вызывают этот SP. Оператор update имеет условие фильтрации для UserId. Каждый пользователь будет выполнять sp только с собственным идентификатором пользователя. Вот почему я создал индекс в столбце UserId.
Ожидание было индексом, чтобы избежать сканирования таблицы, и не будет мертвой блокировки (поскольку каждый пользователь ищет свои собственные записи) ... Но 1 из 10 тестов вызывает мертвую блокировку.
Я считаю, что это связано с тем, что эскалация до table scan
при наличии огромных данных (более 20000 записей каждым пользователем).
Каков наилучший способ избежать взаимоблокировки здесь?
ТАБЛИЦА и индексирует
CREATE TABLE [dbo].[ResultItems](
[SRIID] [int] IDENTITY(1,1) NOT NULL,
[PGM] [nvarchar](50) NULL,
[GRP] [nvarchar](50) NULL,
[PGMGRPSEQ] [nvarchar](50) NULL,
[ITMID] [nvarchar](18) NULL,
[ITMDESC] [nvarchar](255) NULL,
[BRAND] [nchar](40) NULL,
[PackSize] [nvarchar](max) NULL,
[IsSelected] [bit] NULL,
[UserId] [nvarchar](50) NULL,
CONSTRAINT [PK_SEARCH_RESULT_ITEMS] PRIMARY KEY CLUSTERED
(
[SRIID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_PGM_GRP_PGMGRPSEQ_ITMID_UserId] ON [dbo].[ResultItems]
(
[PGM] ASC,
[GRP] ASC,
[PGMGRPSEQ] ASC,
[ITMID] ASC,
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_RESULTITEMS_USERID] ON [dbo].[ResultItems]
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ЛИТЕРАТУРА
- Avoiding Deadlock Transaction Errors by Using ROWLOCK Hint in T-SQL
- INF: Analyzing and Avoiding Deadlocks in SQL Server
- Tips to avoid deadlocks?
Каков уровень изоляции? По умолчанию? Рассматривали ли вы добавление индекса, который фактически разрешает поиск (например, тот, который охватывает все столбцы в предложении JOIN)? Вы также можете добавить дополнительный фильтр 'AND SRI.IsSelected <> 1', потому что нет оснований сопоставлять строки, которые уже были обновлены. –
Вы можете показать CREATE TABLE, включая все индексы? –
@AaronBertrand Добавил данные таблицы/индекса – Lijo