У меня проблема с тупиком в SQL Server, которую мне не удалось устранить.
Как правило, у меня есть большое количество одновременных подключений (от многих машин), которые выполняют транзакции, где они сначала удаляют диапазон записей, а затем повторно вставляют записи в том же диапазоне с массовой вставкой.
По сути, транзакция выглядит следующим образом
BEGIN TRANSACTION T1
DELETE FROM [TableName] WITH( XLOCK HOLDLOCK ) WHERE [Id]=@Id AND [SubId]=@SubId
INSERT BULK [TableName] (
[Id] Int
, [SubId] Int
, [Text] VarChar(max) COLLATE SQL_Latin1_General_CP1_CI_AS
) WITH(CHECK_CONSTRAINTS, FIRE_TRIGGERS)
COMMIT TRANSACTION T1
Массовая вставка вставляет только элементы, соответствующие Id и SubId удаления в той же транзакции. Кроме того, эти записи Id и SubId никогда не должны перекрываться.
Когда у меня достаточно параллельных транзакций этой формы, я начинаю видеть значительное количество тупиковых ситуаций между этими утверждениями.
Я добавил блокирующие подсказки XLOCK HOLDLOCK, чтобы попытаться решить проблему, но, похоже, они не помогают.
Канонический график тупиковой ситуации для этой ошибки показывает:
Соединение 1:
- Содержит RangeX-X на PK_TableName
- Держит IX Page Lock на столе
- Запрос блокировки X-страницы на столе
Соединение 2:
- Держит IX Page Lock на столе
- Запросы на блокировку RangeX-X на столе
Что мне нужно сделать, чтобы эти тупики не возникали.
Я занимался чтением блокировок RangeX-X и не уверен, что полностью понимаю, что с ними происходит. Есть ли у меня какие-либо варианты, кроме блокировки всей таблицы здесь?