В настоящее время я вставляю запись в таблицу 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 ID и Some_Int. Я не думал, что эта последняя информация имеет отношение к делу, поскольку я безуспешно пытался изменить таблицу, чтобы в качестве первичного ключа / кластеризованного индекса использовалось только поле auto inc.
Спасибо.