Triệu chứng
Khi bạn sử dụng hàm SCOPE_IDENTITY() hoặc @@IDENTITY để truy xuất giá trị được chèn vào cột định danh, bạn có thể nhận thấy rằng các hàm này đôi khi trả về giá trị không chính xác. Sự cố chỉ xảy ra khi truy vấn của bạn sử dụng kế hoạch thực thi song song.
Nguyên nhân
Microsoft đã xác nhận rằng đây là sự cố trong các sản phẩm của Microsoft được liệt kê ở đầu bài viết này.
Giải pháp
Thông tin cập nhật tích lũy
SQL Server 2008 R2 Gói Dịch vụ 1
Bản sửa lỗi cho sự cố này lần đầu tiên được phát hành trong Bản cập nhật Tích lũy 5 dành SQL Server 2008 R2 Gói Dịch vụ 1. Để biết thêm thông tin về cách nhận gói cập nhật tích lũy này, hãy bấm vào số bài viết sau để xem bài viết trong Cơ sở Kiến thức Microsoft:
2659694 cập nhật tích lũy gói 5 cho SQL Server 2008 R2 Gói Dịch vụ 1
Lưu ý Vì các bản dựng được tích lũy nên mỗi bản phát hành bản sửa lỗi mới đều chứa tất cả các bản cập nhật nóng và tất cả các bản sửa lỗi bảo mật được tích hợp trong bản phát hành sửa lỗi SQL Server 2008 R2 trước đó. Chúng tôi khuyên bạn nên cân nhắc việc áp dụng bản phát hành sửa lỗi mới nhất có chứa hotfix này. Để biết thêm thông tin, hãy bấm vào số bài viết sau đây để xem bài viết trong Cơ sở Kiến thức Microsoft:
2567616 Bản dựng SQL Server 2008 R2 mới được phát hành sau SQL Server 2008 R2 Gói Dịch vụ 1 được phát hành
Giải pháp thay thế
Microsoft khuyên bạn không sử dụng một trong những chức năng trong truy vấn của bạn khi kế hoạch song song có liên quan như họ không phải lúc nào cũng đáng tin cậy. Thay vào đó, hãy sử dụng mệnh đề OUTPUT của câu lệnh INSERT để truy xuất giá trị căn cước như minh họa trong ví dụ dưới đây.
Ví dụ về cách sử dụng mệnh đề 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
Nếu tình huống của bạn yêu cầu bạn cần phải sử dụng một trong các chức năng này, bạn có thể sử dụng một trong các phương pháp sau đây để giải quyết vấn đề.
Phương pháp 1:
Bao gồm tùy chọn sau đây trong truy vấn của bạn
OPTION (MAXDOP 1)
Lưu ý: Điều này có thể làm tổn hại đến hiệu suất của phần SELECT trong truy vấn của bạn.
Phương pháp 2:
Đọc giá trị từ SELECT một phần vào một tập hợp các biến số (hoặc một biến số bảng duy nhất), rồi chèn vào bảng đích bằng MAXDOP=1. Kể từ khi kế hoạch INSERT sẽ không được song song, bạn sẽ nhận được đúng ngữ điêu, nhưng SELECT bạn sẽ được song song để đạt được hiệu suất mong muốn.
Phương pháp 3:
Chạy câu lệnh sau đây để đặt mức độ tối đa của tùy chọn song song thành 1:
sp\_configure 'max degree of parallelism', 1
go
reconfigure with override
go
Lưu ý: Phương pháp này có thể gây ra sự xuống cấp hiệu suất trên máy chủ. Bạn không nên sử dụng phương pháp này trừ khi bạn đã đánh giá nó trong một thử nghiệm, hoặc dàn, môi trường.