Anda mungkin menerima nilai yang salah saat menggunakan SCOPE_IDENTITY() dan @@IDENTITY

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.

Informasi Selengkapnya

Bug Microsoft Connect pada masalah ini

Tingkat Paralelisme Maks (MAXDOP)