Podczas korzystania z funkcji SCOPE_IDENTITY() i @@IDENTITY mogą być wyświetlane nieprawidłowe wartości

Objawy

W przypadku używania funkcji SCOPE_IDENTITY() lub @@IDENTITY w celu pobrania wartości wstawionych do kolumny tożsamości można zauważyć, że te funkcje czasami zwracają nieprawidłowe wartości. Ten problem występuje tylko wtedy, gdy zapytania korzystają z planów wykonywania równoległego.

Przyczyna

Firma Microsoft potwierdziła, że jest to usterka występująca w produktach firmy Microsoft wymienionych na początku tego artykułu.

Rozwiązanie

Informacje o aktualizacji zbiorczej

SQL Server 2008 R2 z dodatkiem Service Pack 1

Poprawkę rozwiązującą ten problem opublikowano po raz pierwszy w aktualizacji zbiorczej 5 dla programu SQL Server 2008 R2 z dodatkiem Service Pack 1. Aby uzyskać więcej informacji dotyczących sposobu uzyskiwania tego pakietu aktualizacji zbiorczej, kliknij następujący numer artykułu w celu wyświetlenia tego artykułu z bazy wiedzy Baza wiedzy Microsoft Knowledge Base:

2659694 Pakiet aktualizacji zbiorczej 5 dla dodatku Service Pack 1 dla systemu SQL Server 2008 R2

Wskazówka Ponieważ te kompilacje są zbiorcze, każda nowa wersja poprawki zawiera wszystkie poprawki i poprawki zabezpieczeń zawarte w poprzedniej wersji poprawki programu SQL Server 2008 R2. Zalecamy rozważenie zastosowania najnowszej wersji poprawki zawierającej tę poprawkę. Aby uzyskać więcej informacji, kliknij następujący numer artykułu w celu wyświetlenia tego artykułu z bazy wiedzy Baza wiedzy Microsoft Knowledge Base:

2567616 Kompilacje SQL Server 2008 R2 wydane po wydaniu dodatku Service Pack 1 SQL Server 2008 R2

Obejście

Firma Microsoft zaleca, aby nie używać żadnej z tych funkcji w zapytaniach, gdy w grę wchodzą plany równoległe, ponieważ nie zawsze są one niezawodne. Zamiast tego użyj klauzuli OUTPUT instrukcji INSERT, aby pobrać wartość tożsamości, jak pokazano w poniższym przykładzie.

Przykład użycia klauzuli 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

Jeśli w Twojej sytuacji konieczne jest użycie jednej z tych funkcji, możesz użyć jednej z poniższych metod w celu obejścia tego problemu.

Metoda 1.

Uwzględnij następującą opcję w zapytaniu

OPTION (MAXDOP 1)

Uwaga: Może to mieć negatywny wpływ na wydajność SELECT części zapytania.

Metoda 2.

Wczytaj wartość z SELECT części do zestawu zmiennych (lub pojedynczej zmiennej tabeli), a następnie wstaw do tabeli docelowej za pomocą MAXDOP=1. Ponieważ plan INSERT nie będzie równoległy, uzyskasz właściwą semantykę, ale Twój SELECT będzie równoległy, aby osiągnąć pożądaną wydajność.

Metoda 3:

Uruchom następującą instrukcję, aby ustawić opcję maksymalnego stopnia równoległości na 1:

sp\_configure 'max degree of parallelism', 1

go

reconfigure with override

go

Uwaga: ta metoda może spowodować spadek wydajności na serwerze. Nie należy używać tej metody, jeśli nie została ona oceniona w środowisku testowym lub przejściowym.

Więcej informacji

Błąd programu Microsoft Connect dotyczący tego problemu

Maksymalny stopień równoległości (MAXDOP)