Simptome
Atunci când utilizați funcțiile SCOPE_IDENTITY() sau @@IDENTITY pentru a regăsi valorile inserate într-o coloană identitate, este posibil să observați că aceste funcții returnează uneori valori incorecte. Problema apare numai atunci când interogările utilizează planuri de executare paralelă.
Cauză
Microsoft a confirmat că aceasta este o problemă în produsele Microsoft listate la începutul acestui articol.
Rezolvare
Informații despre actualizarea cumulativă
SQL Server 2008 R2 Service Pack 1
Remedierea pentru această problemă a fost lansată pentru prima dată în actualizarea cumulativă 5 pentru SQL Server 2008 R2 Service Pack 1. Pentru informații suplimentare despre cum să obțineți acest pachet de actualizări cumulative, faceți clic pe următorul număr de articol pentru a vedea articolul în Baza de cunoștințe Microsoft:
2659694 Actualizarea cumulativă pachetul 5 pentru SQL Server 2008 R2 Service Pack 1
Notă Deoarece compilările sunt cumulative, fiecare lansare de remediere nouă conține toate remedierile rapide și toate remedierile de securitate care au fost incluse cu lansarea anterioară de remediere a SQL Server 2008 R2. Vă recomandăm să luați în considerare aplicarea celei mai recente remedieri care conține această remediere rapidă. Pentru mai multe informații, faceți clic pe următorul număr de articol pentru a-l vedea în Baza de cunoștințe Microsoft:
2567616 Compilările SQL Server 2008 R2 lansate după lansarea SQL Server 2008 R2 Service Pack 1
Soluție
Microsoft recomandă să nu utilizați niciuna dintre aceste funcții în interogări atunci când sunt implicate planuri paralele, deoarece nu sunt întotdeauna fiabile. În schimb, utilizați clauza OUTPUT a instrucțiunii INSERT pentru a regăsi valoarea de identitate, așa cum se arată în exemplul de mai jos.
Exemplu de utilizare a clauzei 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
Dacă situația dvs. necesită să utilizați oricare dintre aceste funcții, puteți utiliza una dintre metodele următoare pentru a evita problema.
Metoda 1:
Includeți următoarea opțiune în interogare
OPTION (MAXDOP 1)
Notă: acest lucru poate afecta performanța părții SELECT a interogării.
Metoda 2:
Citiți valoarea dintr-o SELECT parte dintr-un set de variabile (sau o variabilă dintr-un singur tabel), apoi inserați în tabelul țintă cu MAXDOP=1. Deoarece planul INSERT nu va fi paralel, veți obține semantica potrivită, dar SELECT veți fi paralel pentru a obține performanța dorită.
Metoda 3:
Rulați următoarea instrucțiune pentru a seta opțiunea grad maxim de paralelism la 1:
sp\_configure 'max degree of parallelism', 1
go
reconfigure with override
go
Notă: Această metodă poate provoca degradarea performanței serverului. Nu trebuie să utilizați această metodă decât dacă ați evaluat-o într-un mediu de testare sau de etapizare.