Проблема заключается в выполнении выбора, а затем вставки, затем обычно есть блокировка чтения для выбора, а затем блокировка записи на вставке. Без транзакции время многих обновлений часто позволяет выполнить несколько вставок, как вы видите. В транзакции первая блокировка чтения остановит другие процессы, получающие блокировку записи, и если более одного процесса получит блокировку чтения, то ни один не сможет получить блокировку записи, и вы получите тупик.
В этом случае я бы изменил код вставки так, чтобы индексы позволяли работать только одной вставке, т. Е. У вас есть уникальный ключ, и только один процесс не сможет вставить данные, чтобы не было дубликатов.
Процесс обновления в транзакции либо
1) сначала выполнить вставку и устранить исключение или ошибку, если попытается вставить дубликат
или 2) выполнить HOLD LOCK (Sybase и SQL Server) при первом выполнении выбора - таким образом первый блокирующий получает полное разрешение на вставку при необходимости
или 3) Возможно, используйте команду слияния, если СУБД это позволяет. Это выполнит проверку и вставит все в одну команду, но всегда изменит базу данных.
EDIT:
Я думаю, что реальной альтернативы 1 не существует, если вам нужно убедиться, что в транзакцию вставлена одна и только одна запись, которая должна быть в транзакции.
стоимость может быть снижена путем проверки наличия forst в одной транзакции, а затем, во-вторых, путем вставки и проверки в другой транзакции. Таким образом, в большинстве случаев у вас просто есть выборка, а в других - полная медленная вставка и проверка, но это должно происходить реже.