У меня проблема с взаимоблокировкой в 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 никогда не должны перекрываться.
Когда у меня достаточно параллельных транзакций этой формы, я начинаю видеть значительное количество взаимоблокировок между этими операторами.
Я добавил подсказки блокировки XLOCK HOLDLOCK, чтобы попытаться решить проблему, но, похоже, они не помогают.
Канонический график взаимоблокировок для этой ошибки показывает:
Соединение 1:
- Удерживает RangeX-X на PK_TableName
- Удерживает блокировку страницы IX на столе
- Запрос блокировки страницы X на столе
Соединение 2:
- Удерживает блокировку страницы IX на столе
- Запрашивает блокировку RangeX-X на столе
Что мне нужно сделать, чтобы убедиться, что эти взаимоблокировки не возникают.
Я кое-что читал о замках RangeX-X и не уверен, что полностью понимаю, что с ними происходит. Есть ли у меня какие-либо варианты, кроме блокировки всей таблицы здесь?