В настоящее время я вставляю запись в таблицу SQL Server, а затем выбираю идентификатор автоинкремента следующим образом:
(@p0 int,@p1 nvarchar(8))INSERT INTO [dbo].[Tag]([Some_Int], [Tag])
VALUES (@p0, @p1)
SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value]
(Это было сгенерировано с использованием Linq-to-SQL). По какой-то причине, когда я запускаю этот код внутри транзакции, используя объект TransactionScope с Serializable уровнем изоляции, SQL Server выдает ошибку взаимоблокировки. Я проанализировал события графа взаимоблокировки и обнаружил, что оба вовлеченных процесса ожидают друг от друга выполнения операции преобразования, поскольку я понимаю следующую информацию:
<resource-list>
<keylock hobtid="72057594101170176" dbid="5" objectname="foo.dbo.Tag" indexname="PK_Tag_1" id="lockb77cdc0" mode="RangeS-S" associatedObjectId="72057594101170176">
<owner-list>
<owner id="processc9be40" mode="RangeS-S"/>
</owner-list>
<waiter-list>
<waiter id="processc9ae38" mode="RangeI-N" requestType="convert"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594101170176" dbid="5" objectname="foo.dbo.Tag" indexname="PK_Tag_1" id="lockb77cdc0" mode="RangeS-S" associatedObjectId="72057594101170176">
<owner-list>
<owner id="processc9ae38" mode="RangeS-S"/>
</owner-list>
<waiter-list>
<waiter id="processc9be40" mode="RangeI-N" requestType="convert"/>
</waiter-list>
</keylock>
</resource-list>
Насколько я понимаю, область транзакции не позволит второму процессу выполнить вставку, пока первый не завершит вставку и выбор идентификатора. Однако, похоже, это не так. Может ли кто-нибудь пролить свет на лучший подход к достижению того, что мне нужно, в поточно-ориентированном виде?
- Обновлено -
Просто чтобы отметить; Я на 99% уверен, что между этими двумя процессами нет общего подключения, поскольку каждый создает новый DataContext для связи с базой данных.
- Обновление снова -
Ремус Русану указал, что некоторая пропущенная информация связана с проблемой, я попытался упростить сценарий на основе отчета о графике тупиковой ситуации, но здесь я расширил объяснение. Перед тем, как выполнить вставку, я выполняю запрос на существующую таблицу, чтобы определить, существует ли тег. Если это так, я заканчиваю транзакцию. Если нет, вставка должна продолжаться, и тогда я выполняю обновление, не показанное здесь, для таблицы, в которой первичный ключ имеет Some_Int
, хотя обновление предназначено исключительно для последнего измененного значения. Также может быть важно, чтобы таблица тегов имела кластеризованный индекс, состоящий из идентификатора auto inc и Some_Int. Я не думал, что эта последняя часть информации была релевантной, так как я пытался изменить таблицу так, чтобы в качестве первичного ключа / кластеризованного индекса использовалось только поле auto inc.
Спасибо.