Проблемы
При использовании функций SCOPE_IDENTITY() или @@IDENTITYдля получения значений, вставленных в столбец удостоверений, вы можете заметить, что иногда эти функции возвращают неправильные значения. Проблема возникает только в том случае, если запросы используют параллельные планы выполнения. Дополнительные сведения о том, как определить, будут ли ваши запросы использовать параллельные планы выполнения, можно найти в разделе Параллелизм intra-query в следующей технической статье о загрузках Майкрософт:
Причина
Корпорация Майкрософт подтверждает, что это проблема в продуктах Майкрософт, перечисленных в начале этой статьи.
Решение
Сведения о накопительном пакете обновления
SQL Server 2008 R2 с пакетом обновления 1
Исправление для этой проблемы впервые выпущено в накопительном обновлении 5 для SQL Server 2008 R2 с пакетом обновления 1 (SERVICE PACK 1). Чтобы узнать больше о том, как получить этот пакет накопительного пакета обновления, щелкните номер следующей статьи, чтобы просмотреть статью в базе знаний Майкрософт:
2659694Пакет накопительного обновления 5 для SQL Server 2008 R2 с пакетом обновления 1
Примечание.Так как сборки являются накопительными, каждый новый выпуск исправлений содержит все исправления и исправления для системы безопасности, которые были включены в предыдущий выпуск исправлений SQL Server 2008 R2. Рекомендуем применить последний выпуск исправлений, содержащий этот исправление. Дополнительные сведения см. в следующей статье базы знаний Майкрософт:
2567616Сборки SQL Server 2008 R2, выпущенные после выпуска SQL Server 2008 R2 с пакетом обновления 1
Обходное решение
Корпорация Майкрософт рекомендует не использовать эти функции в запросах, если параллельные планы связаны с этими функциями, так как они не всегда надежны. Вместо этого используйте предложение OUTPUT в предложении INSERT, чтобы получить значение удостоверения, как показано в примере ниже.
Пример использования предложения OUTPUT:
DECLARE @MyNewIdentityValues таблица(myidvalues int)
объявить @A (первичный ключ ИД int)
вставка @A значений (1)
объявление @B (идентификатор первичного ключа ID int(1;1), B int not null)
вставка @B значений (1)
выберите
[RowCount] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE_IDENTITY] = SCOPE_IDENTITY()
настройка профиля статистики в
вставка в _ddr_T
вывод inserted.ID в @MyNewIdentityValues
выберите
b.ID
из @A a
left join @B b on b.ID = 1
left join @B b2 on b2. B = -1
left join _ddr_T t on t.T = -1
где нет (выберите * из _ddr_T t2, где t2.ID = -1)
отключение профиля статистики
выберите
[RowCount] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE_IDENTITY] = SCOPE_IDENTITY(),
[IDENT_CURRENT] = IDENT_CURRENT('_ddr_T')
выберите * в @MyNewIdentityValues
Пойти
Если в вашей ситуации требуется использовать одну из этих функций, вы можете воспользоваться одним из указанных ниже способов.
Способ 1.
Включите в запрос следующий параметр:
OPTION (MAXDOP 1)
Примечание.Это может повредить производительность части запроса SELECT.
Способ 2.
Считыйте значение из части SELECT в набор переменных (или одно табличная переменная), а затем вставьте его в целевую таблицу с помощью MAXDOP=1. Так как план INSERT не будет параллельным, вы получите правильный семантический результат, а select будет параллельным, чтобы добиться нужной производительности.
Способ 3.
Чтобы установить для параметра максимального уровня параллелизма максимальное степень параллелизма 1:
sp_configure "максимум степени параллелизма", 1
Пойти
перенастройка с помощью переопределения
Пойти
Примечание.Этот метод может привести к снижению производительности на сервере. Этот метод следует использовать только после его оценки в тестовой или промежуточной среде.