INSERT INTO .. ​​SELECT .. уникальное нарушение ограничений

Я запускаю хранимую процедуру, которая выбирает значения моей временной таблицы и вставляет их в базу данных следующим образом:

INSERT INTO emails (EmailAddress) ( SELECT DISTINCT eit.EmailAddress FROM #EmailInfoTemp eit LEFT JOIN emails ea ON eit.EmailAddress = ea.EmailAddress WHERE ea.EmailAddressID IS NULL ) 

В редких случаях (~ один раз каждые пару часов на сервере, который обрабатывает тысячи запросов в минуту), я получаю уникальную ошибку ограничения «Нарушение ограничения UNIQUE KEY» … в индексе в столбце EmailAddress.

Я могу подтвердить, что я не перехожу в двойные значения. Даже если бы я был, это должно быть уловлено DISTINCT.

-SQL Server 2008 -Установил proc + не используя транзакции + JDBC callablestatement

Может ли случиться, что между SELECT и последующим INSERT был другой вызов того же / другого сохраненного proc, который завершил INSERT с подобными данными? Если да, то каким будет лучший способ предотвратить это?

Некоторые идеи. У нас есть много дублирующих экземпляров «клиентов», которые сразу же взаимодействуют с этим SQL Server, поэтому моя первая реакция была проблемой параллелизма, но я не могу воспроизвести ее сам. Это лучшее, что у меня было, но до сих пор его никуда не было. Это не происходит в нашей промежуточной среде, где нагрузка невелика по сравнению с производственной средой. Это была основная причина, по которой я начал изучать проблемы параллелизма.

Вероятно, ошибка вызвана двумя сеансами, выполняющими вставку в одно и то же время.

Вы можете сделать код SQL более безопасным, используя MERGE . Как говорится в комментарии Аарона Бертранда (спасибо!), Вы должны включить подсказку with (holdlock) чтобы сделать merge действительно безопасным .

 ; merge emails e with (holdlock) using #EmailInfoTemp eit on e.EmailAddress = eit.EmailAddress when not matched then insert (EmailAddress) values (eit.EmailAddress) 

Оператор merge принимает соответствующие блокировки, чтобы гарантировать, что никакой другой сеанс не может прокрасться между его «несоответствующей» проверкой и «вставкой».

Если вы не можете использовать merge , вы можете решить проблему на стороне клиента. Убедитесь, что две вставки не работают одновременно. Это обычно легко сделать с помощью мьютекса или другой конструкции синхронизации.

Interesting Posts

Получение конверсии не удалось при преобразовании значения varchar 'string' в datatype int

Конкретный день текущего месяца и года

Как я могу вывести список идентификаторов из таблицы SQL в виде строки значений, разделенных запятыми?

Вывод транзакции SQL-сервера с использованием Perl DBI

Импорт данных в Excel из запроса SQL Server

SQL-запрос с SUM с группой по

Может ли INSERT <table> (x) VALUES (@x) НЕ СУЩЕСТВУЕТ (SELECT * FROM <table> WHERE x = @x) вызывает дубликаты?

Открыть двоичный файл из базы данных C #

RANDBETWEEN для SQL Server 2012

Замените все адреса электронной почты после @ в Sql

создайте динамический, где в sql SP

Как проверить безопасность изменения уровня совместимости базы данных SQL Server?

Удаление повторяющихся данных Преобразование C # в SQL

Ошибка SSIS: недопустимое имя объекта – но объект существует и выполняется запрос в SSMS

Запрос быстрый, но когда в VIEW, он медленный – из-за ROW_NUMBER

Давайте будем гением компьютера.