Симптоми
Когато използвате функции SCOPE_IDENTITY() или @@IDENTITY за извличане на стойностите, вмъкнати в колона за самоличност, е възможно да забележите, че тези функции понякога връщат неправилни стойности. Проблемът възниква само когато вашите заявки използват паралелни планове за изпълнение.
Причина
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:
DECLARE @MyNewIdentityValues table(myidvalues int)
declare @A table (ID int primary key)
insert into @A values (1)
declare @B table (ID int primary key identity(1,1), B int not null)
insert into @B values (1)
select
[RowCount] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE\_IDENTITY] = SCOPE\_IDENTITY()
set statistics profile on
insert into \_ddr\_T
output inserted.ID into @MyNewIdentityValues
select
b.ID
from @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
where not exists (select \* from \_ddr\_T t2 where t2.ID = -1)
set statistics profile off
select
[RowCount] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE\_IDENTITY] = SCOPE\_IDENTITY(),
[IDENT\_CURRENT] = IDENT\_CURRENT('\_ddr\_T')
select \* from @MyNewIdentityValues
go
Ако вашата ситуация изисква да използвате някоя от тези функции, можете да използвате един от следните методи за заобиколно решение на проблема.
Метод 1:
Включете следната опция във вашата заявка
OPTION (MAXDOP 1)
Забележка: Това може да влоши производителността на част от заявката SELECT.
Метод 2:
Прочетете стойността от SELECT частта в набор от променливи (или променлива от една таблица) и след това я вмъкнете в целевата таблица с MAXDOP=1. Тъй като планът INSERT няма да е успореден, ще получите правилната семантика, но SELECT ще бъдете успоредни, за да постигнете желаната производителност.
Метод 3:
Изпълнете следната команда, за да зададете опцията за максимална степен на паралелизъм на 1:
sp\_configure 'max degree of parallelism', 1
go
reconfigure with override
go
Забележка: Този метод може да влоши производителността на сървъра. Не трябва да използвате този метод, освен ако не сте го оценили в тестова или постановъчна среда.