Gejala
Ketika menggunakan fungsi SCOPE_IDENTITY() atau @@IDENTITY untuk mengambil nilai yang disisipkan ke dalam kolom identitas, Anda mungkin melihat bahwa fungsi ini terkadang mengembalikan nilai yang salah. Masalah hanya terjadi jika kueri Anda menggunakan rencana eksekusi paralel.
Penyebab
Microsoft telah mengonfirmasi bahwa ini adalah masalah pada produk Microsoft yang tercantum di awal artikel ini.
Resolusi
Informasi pembaruan kumulatif
SQL Server 2008 R2 Paket Layanan 1
Perbaikan untuk masalah ini pertama kali dirilis dalam Pembaruan Kumulatif 5 untuk SQL Server 2008 R2 Paket Layanan 1. Untuk informasi selengkapnya tentang cara mendapatkan paket pembaruan kumulatif ini, klik nomor artikel berikut untuk melihat artikel di Pangkalan Pengetahuan Microsoft:
2659694 Pembaruan Kumulatif paket 5 untuk SQL Server 2008 R2 Paket Layanan 1
catatan Karena build bersifat kumulatif, setiap rilis perbaikan baru berisi semua hotfix dan semua perbaikan keamanan yang disertakan dengan rilis perbaikan SQL Server 2008 R2 sebelumnya. Kami menyarankan Anda mempertimbangkan untuk menerapkan rilis perbaikan terbaru yang berisi hotfix ini. Untuk informasi selengkapnya, klik nomor artikel berikut untuk melihat artikel di Pangkalan Pengetahuan Microsoft:
2567616 Build R2 SQL Server 2008 yang dirilis setelah SQL Server 2008 R2 Paket Layanan 1 dirilis
Solusi
Microsoft menyarankan agar Anda tidak menggunakan salah satu fungsi ini dalam kueri saat paket paralel terlibat, karena fungsi tersebut tidak selalu dapat diandalkan. Sebagai gantinya, gunakan klausa OUTPUT dari pernyataan INSERT untuk mengambil nilai identitas seperti yang ditunjukkan dalam contoh di bawah ini.
Contoh penggunaan klausa 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
Jika situasi Anda mengharuskan Anda menggunakan salah satu fungsi ini, Anda dapat menggunakan salah satu metode berikut untuk mengatasi masalah tersebut.
Metode 1:
Sertakan opsi berikut dalam kueri Anda
OPTION (MAXDOP 1)
Catatan: Hal ini dapat merusak performa PILIH bagian kueri Anda.
Metode 2:
Baca nilai dari SELECT bagian ke dalam sekumpulan variabel (atau variabel tabel tunggal) lalu sisipkan ke dalam tabel target dengan MAXDOP=1. Karena rencana INSERT tidak akan paralel, Anda akan mendapatkan semantik yang tepat, namun Anda SELECT akan paralel untuk mencapai kinerja yang diinginkan.
Metode 3:
Jalankan pernyataan berikut untuk mengatur opsi tingkat paralelisme maksimum ke 1:
sp\_configure 'max degree of parallelism', 1
go
reconfigure with override
go
Catatan: Metode ini dapat menyebabkan penurunan kinerja pada server. Anda tidak boleh menggunakan metode ini kecuali Anda telah mengevaluasinya dalam lingkungan pengujian, atau pementasan.