Симптоми
Когато използвате или SCOPE_IDENTITY(),или @@IDENTITY,за да извлечете стойностите, вмъкнати в колона за самоличност, може да забележите, че тези функции понякога връщат неправилни стойности. Проблемът възниква само когато заявките ви използват паралелни планове за изпълнение. За повече информация как да определите дали заявките ви ще използват планове за паралелно изпълнение, вижте секцията "Паралелизъм между заявките" в следната техническа статия за изтегляния на Microsoft:
Причина
Microsoft потвърди, че това е проблем в продуктите на Microsoft, които са изброени в началото на тази статия.
Решение
Информация за кумулативна актуализация
SQL Server 2008 R2 Service Pack 1
Корекцията за този проблем за първи път е издадена в кумулативна актуализация 5 за SQL Server 2008 R2 Service Pack 1. За повече информация как да получите този кумулативен пакет за актуализация щракнете върху следния номер на статия в базата знания на Microsoft:
2659694Пакет със сборни актуализации 5 за SQL Server 2008 R2 Service Pack 1
Забележка Тъй като компилките са кумулативни, всяко ново издание на корекцията съдържа всички актуални корекции и всички корекции на защитата, които са били включени в предишното издание на корекцията на SQL Server 2008 R2. Препоръчваме ви да приложите най-новата версия на корекцията, която съдържа тази актуална корекция. За допълнителна информация щракнете върху следния номер на статия, за да прегледате статията в базата знания на Microsoft:
2567616Компилитети на SQL Server 2008 R2, издадени след издадения SQL Server 2008 R2 Service Pack 1
Заобиколно решение
Microsoft препоръчва да не използвате нито една от тези функции във вашите заявки, когато са включени паралелни планове, тъй като те не винаги са надеждни. Вместо това използвайте клаузата OUTPUT на командаТА INSERT, за да извлечете стойността на самоличност, както е показано в примера по-долу.
Пример за използване на клауза OUTPUT:
ТАБЛИЦА @MYNEWIDENTITYVALUES(myidvalues int)
деклариране @A таблица (ИД int първичен ключ) вмъкване в @A стойности (1) деклариране @B (ИД int primary key identity(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 ляво съединение @B b2 на b2. B = -1 left join _ddr_T t на 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:
Включете следната опция във вашата заявка
ОПЦИЯ (MAXDOP 1)
Забележка:Това може да навреди на производителността на част от вашата заявка SELECT.
Метод 2:
Прочетете стойността от частта SELECT в набор от променливи (или една променлива на таблица) и след това вмъкнете в целевата таблица с MAXDOP=1. Тъй като планът INSERT няма да бъде успореден, ще получите правилното семантично, но вашият SELECT ще бъде успореден, за да постигнете желаната производителност.
Метод 3:
Изпълнете следната команда, за да зададете опцията за максимална степен на паралелизъм на 1:
sp_configure "максимална степен на паралелизъм", 1
отидете
преконфигуриране с заместване
отидете
Забележка:Този метод може да доведе до влошаване на производителността на сървъра. Не трябва да използвате този метод, освен ако не сте го оценили в тестване или спиране на среда.