Symptom
När du använder antingen SCOPE_IDENTITY() eller @@IDENTITYför att hämta värden som infogats i en identitetskolumn kanske du märker att dessa funktioner ibland returnerar felaktiga värden. Problemet uppstår bara när dina frågor använder parallella körningsplaner. Mer information om hur du fastställer om dina frågor ska använda parallella körningsplaner finns i avsnittet om parallellitet mellan årsfråga i följande tekniska artikel om Microsoft-nedladdningar:
Orsak
Microsoft har bekräftat att det är ett problem i de Microsoft-produkter som listas i början av den här artikeln.
Lösning
Information om kumulativ uppdatering
SQL Server 2008 R2 Service Pack 1
En korrigering för det här problemet släpptes först i kumulativ uppdatering 5 för SQL Server 2008 R2 Service Pack 1. Om du vill ha mer information om hur du hämtar det kumulativa uppdateringspaketet klickar du på följande artikelnummer för att visa artikeln i Microsoft Knowledge Base:
2659694Kumulativ uppdateringspaket 5 för SQL Server 2008 R2 Service Pack 1
Obs! Eftersom versionerna är kumulativa innehåller varje ny korrigeringsversion alla snabbkorrigeringar och alla säkerhetskorrigeringar som ingick i den tidigare SQL Server 2008 R2-korrigeringsuppdateringen. Vi rekommenderar att du använder den senaste korrigeringsutgåren som innehåller den här snabbkorrigeringen. Om du vill veta mer klickar du på följande artikelnummer och läser artikeln i Microsoft Knowledge Base:
2567616SQL Server 2008 R2-versionerna som släpptes efter att SQL Server 2008 R2 Service Pack 1 släpptes
Lösning
Microsoft rekommenderar att du inte använder någon av de här funktionerna i dina frågor när parallella planer ingår, eftersom de inte alltid är tillförlitliga. Använd i stället OUTPUT-satsen i INSERT-instruktionen för att hämta identitetsvärdet som visas i exemplet nedan.
Exempel på användning av OUTPUT-satsen:
DECLARE @MyNewIdentityValues table(myidvalues int)
deklarera @A (ID int primary key)
infoga i @A (1)
deklarera @B (ID i primärnyckelns identitet(1,1), B int not null)
infoga i @B (1)
väljer du
[RowCount] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE_IDENTITY] = SCOPE_IDENTITY()
ställ in statistikprofilen på
infoga i _ddr_T
utdata inserted.ID i @MyNewIdentityValues
väljer du
b.ID
från @A a
vänster koppling @B b på b.ID = 1
vänster koppling @B b2 på b2. B = -1
vänster koppling _ddr_T t på t.T = -1
där det inte finns (välj * från _ddr_T t2 där t2.ID = -1)
ställa in statistikprofilen inaktiverad
väljer du
[RowCount] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE_IDENTITY] = SCOPE_IDENTITY(),
[IDENT_CURRENT] = IDENT_CURRENT('_ddr_T')
välj * från @MyNewIdentityValues
gå till
Om din situation kräver att du behöver använda någon av de här funktionerna kan du använda någon av följande metoder för att lösa problemet.
Metod 1:
Inkludera följande alternativ i frågan
ALTERNATIV (MAXDOP 1)
Obs!Det här kan skada prestandan för SELECT-delen av frågan.
Metod 2:
Läs värdet från SELECT-delen i en uppsättning variabler (eller en tabellvariabel) och infoga det sedan i måltabellen med MAXDOP=1. Eftersom INSERT-planen inte kommer att vara parallell kommer du att få rätt semantik, men din SELECT kommer att vara parallell för att uppnå önskad prestanda.
Metod 3:
Kör följande uttryck för att ange det maximala parallellitetsalternativet till 1:
sp_configure 'max degree of parallelism', 1
gå till
konfigurera om med åsidosättning
gå till
Obs!Den här metoden kan medföra försämrad prestanda på servern. Du bör inte använda den här metoden om du inte har utvärderat den i en testnings- eller mellanlagringsmiljö.