Что SELECT @@IDENTITY вернет, если у меня будет транзакционный запрос с IsolationLevel.Snapshot в множественном и одновременном запросе?

У меня есть доступ к таблице из нескольких приложений с несколькими транзакциями, и я хочу, чтобы эти несколько приложений / транзакций вставляли каждый первичный ключ / идентификатор соответствующим образом приложением, которое выполняет эту транзакцию. По какой-то причине я не могу использовать SCOPE_IDENTITY, поэтому моя последняя сортировка - @@IDENTITY. Для транзакционного запроса я реализовал IsolationLevel.Snapshot для каждой транзакции, чтобы избежать блокировки.

Теперь мой вопрос: будет ли каждая транзакция возвращать @@IDENTITY правильно и в соответствии с этим сценарием.

Ex. У меня три запроса выполняются одновременно:

  • Transactional1 Query Insert с ожидаемым идентификатором возврата 100;
  • Transactional2 Query Insert с ожидаемым идентификатором возврата 102;
  • Transactional3 Query Insert с ожидаемым идентификатором возврата 103;

Будет ли он возвращать идентичность соответственно, как это? это моя цель

  • Транзакция 1 - 100
  • Транзакция 2 - 102
  • Транзакция3 - 103

Или это может случиться так? это я боюсь случиться

  • Транзакция 1 - 102
  • Транзакция 2 - 103
  • Транзакция3 - 101

Этот существующий триггер является причиной, по которой SCOPE_IDENTITY возвращает идентичность, даже если в моем коде и запросе есть SCOPE_IDENTITY.

ALTER trigger [dbo].[CustomerAddressesInsertVIds] on [dbo].[CustomerAddresses]
instead of insert
as
begin
set nocount on
insert into [dbo].[CustomerAddresses]
([CustomerID], [AddressTypeID], [CustomerAddressID], [AddressNameType], [Name], [ContactID], [Address1], [Address2], [Address3], [City], [County], [State], [Country], [Zip], [Phone1], [Phone2], [Fax1], [Fax2], [CreateDate], [CreateUser], [MaintenanceDate], [MaintenanceUser], [LastOrderDate], [DeleteOnDate], [SyncStatus], [SyncDate], [SyncUser], [ERPID], [CreateCustomerID], [CreateContactID], [MaintenanceCustomerID], [MaintenanceContactID], [Active], [Deleted], [LockUser], [LockSessionID], [LockDate], [InUse], [AddressTypeVId], [CustomerVId])
select
coalesce([CustomerID], (select [CustomerID] from [dbo].[Customers] where [CustomerVId]=inserted.[CustomerVId])), coalesce([AddressTypeID], (select [AddressTypeID] from [dbo].[AddressTypes] where [AddressTypeVId]=inserted.[AddressTypeVId])), [CustomerAddressID], [AddressNameType], [Name], [ContactID], [Address1], [Address2], [Address3], [City], [County], [State], [Country], [Zip], [Phone1], [Phone2], [Fax1], [Fax2], [CreateDate], [CreateUser], [MaintenanceDate], [MaintenanceUser], [LastOrderDate], [DeleteOnDate], [SyncStatus], [SyncDate], [SyncUser], [ERPID], [CreateCustomerID], [CreateContactID], [MaintenanceCustomerID], [MaintenanceContactID], [Active], [Deleted], [LockUser], [LockSessionID], [LockDate], [InUse], coalesce([AddressTypeVId], (select [AddressTypeVId] from [dbo].[AddressTypes] where [AddressTypeID]=inserted.[AddressTypeID])), coalesce([CustomerVId], (select [CustomerVId] from [dbo].[Customers] where [CustomerID]=inserted.[CustomerID]))
from inserted
end

1 ответ

Большинство важных деталей описаны в документации:

@@IDENTITY а также SCOPE_IDENTITY вернуть последнее значение идентичности, сгенерированное в любой таблице в текущем сеансе. Тем не мение, SCOPE_IDENTITY возвращает значение только в пределах текущей области видимости; @@IDENTITY не ограничивается конкретной областью применения.

Есть также подробности о том, как @@IDENTITY может возвращать неожиданные значения - но все они связаны (как и следовало ожидать) с областью, а не с другими сеансами.

Единственная функция в этом наборе, которая касается, если вы имеете дело с другими сессиями, это IDENT_CURRENT,

Конечно, если ваш код также имеет дело с триггерами (которые создают вложенные области видимости), которые также манипулируют таблицами со значениями идентичности (вызывая @@IDENTITY вернуть "неправильное" значение), и вы уже исключили SCOPE_IDENTITY почему-то тебе не повезло.

Другие вопросы по тегам