У меня есть база данных с READ_COMMITTED_SNAPSHOT_ISOLATION, установленной в ON (не могу изменить это).
Я вставляю новые строки в таблицу на многих параллельных сеансах, но только если их там еще нет (classi c) проверка левого соединения).
Код вставки выглядит следующим образом:
INSERT INTO dbo.Destination(OrderID)
SELECT DISTINCT s.OrderID
FROM dbo.Source s
LEFT JOIN dbo.Destination d ON d.OrderID = s.OrderID
WHERE d.OrderID IS NULL;
Если я запускаю это во многих параллельных сеансах, я получаю много повторяющихся ошибок ключа, так как разные сеансы пытаются вставить одни и те же идентификаторы OrderID снова и снова.
Это ожидается из-за отсутствия блокировок SHARED в RCSI.
Здесь (согласно моим исследованиям) рекомендуется использовать подсказку READCOMMITTEDLOCK. как это:
LEFT JOIN dbo.Destination d WITH (READCOMMITTEDLOCK) ON d.OrderID = s.OrderID
Это несколько работает, так как значительно уменьшает ошибки дубликата ключа, но (к моему удивлению) не устраняет их полностью.
В качестве эксперимента я удалил уникальное ограничение на таблицу назначения и увидел, что много дубликатов входит в таблицу в одну и ту же миллисекунду, возникшую из разных сеансов.
Кажется, что несмотря на подсказку таблицы, я все еще получаю ложный положительный результат при проверке существования и срабатывает избыточная вставка.
Я пробовал разные подсказки (SERIALIZABLE), но это сделало его хуже и скопилось меня с тупиками.
Как я могу заставить эту вставку работать под RCSI?