10

Tiếp theo tuyên bố:Snapshot giao dịch cách ly bị hủy bỏ do để cập nhật xung đột

INSERT INTO dbo.Changes([Content], [Date], [UserId], [CompanyId]) 
    VALUES (@1, @2, @3, @4); 
SELECT @@identity; 

mang lại cho tôi lỗi SQL này 3960:

ly Snapshot giao dịch bị hủy bỏ do để cập nhật xung đột. Bạn không thể sử dụng tính năng cô lập ảnh chụp để truy cập bảng 'dbo.Companies' trực tiếp hoặc gián tiếp trong cơ sở dữ liệu 'myDatabase' để cập nhật, xóa hoặc chèn hàng đã được sửa đổi hoặc xóa bởi một giao dịch khác. Thử lại giao dịch hoặc thay đổi mức cách ly cho tuyên bố cập nhật/xóa .

Theo như tôi đã hiểu, từ thông báo lỗi, tôi không nên cập nhật, xóa hoặc chèn vào bảng dbo.Companies trong thời gian kết nối khác đang sửa đổi dbo.Companies.

Nhưng tại sao nó xảy ra khi tôi đã chèn một hàng mới vào một bảng dbo.Changes (trong đó có chính nước ngoài để dbo.Companies) và tôi đã không xóa hàng được tham chiếu trong dbo.Companies, nhưng tôi đã chỉ cập nhật hàng trong dbo.Companies và không phải là chính Chìa khóa? Điều này sẽ làm việc ok, phải không? (Có một lỗi trong SQL Server?)

UPDATE:

Bàn trông giống như sau:

dbo.Changes([Id] int PK, [Content] nvarchar, 
    [Date] datetime, [UserId] int, [CompanyId] int -> dbo.Companies.[Id]) 
dbo.Companies([Id] int PK, [Name] nvarchar) 

cập nhật thứ hai được thực hiện:

UPDATE dbo.Companies WHERE [Id] = @1 SET [Name] = @2; 

Trả lời

5

Có vẻ SQL Máy chủ sẽ nhận được các khóa cập nhật trên bất kỳ bản ghi nào mà nó phải đọc ngay cả khi nó không sửa đổi nó. Thông tin

Thông tin thêm về microsoft.public.sqlserver.server thread này:

Nếu không có một chỉ số hỗ trợ trên CustomerContactPerson, báo cáo kết quả

DELETE FROM ContactPerson ĐÂU ID = @ID;

Sẽ yêu cầu một "hiện tại" đọc tất cả các hàng trong CustomerContactPerson để đảm bảo rằng có không có CustomerContactMọi hàng tham chiếu đến hàng đã xóa ContactPerson. Với chỉ mục, DELETE có thể xác định rằng không có hàng liên quan nào trong CustomerContactPerson mà không đọc các hàng bị ảnh hưởng bởi giao dịch khác.

Ngoài ra, trong ảnh chụp nhanh giao dịch mẫu để đọc dữ liệu mà bạn sắp bật xung quanh và cập nhật là lấy UPDLOCK khi bạn đọc. Điều này đảm bảo rằng bạn đang thực hiện cập nhật dựa trên dữ liệu "hiện tại", chứ không phải dữ liệu " " nhất quán "và rằng khi bạn phát hành DML, dữ liệu sẽ không bị khóa và bạn đã thắng ' t vô tình ghi đè thay đổi khác của phiên .

Việc sửa chữa đối với chúng tôi là thêm chỉ số cho các phím nước ngoài

Trong ví dụ của bạn, tôi nghi ngờ thêm một chỉ số để Changes.CompanyId sẽ giúp. Tôi không chắc đây có phải là giải pháp thực sự hay không. Trình tối ưu hóa SQL Server có thể chọn không sử dụng chỉ mục không?

+0

Cảm ơn bạn đã gợi ý, nhưng nó dường như không giúp đỡ. –

+0

Cả hai câu lệnh (INSERT và UPDATE) đều có cùng một khách hàng không? Nếu vậy, chúng tôi không may mắn như tôi biết. –

+0

Có, chèn đang sử dụng id của công ty đang cập nhật. –

3

SQL Server có thể nhìn thấy một bản cập nhật cho một bảng phụ thuộc có COULD sửa đổi hành vi của chèn ... có vẻ công bằng với tôi khi SQL không thể đoán được logic nào khác có thể phụ thuộc o n [name] cột (gây nên vv)

nếu ứng dụng của bạn thực hiện bế tắc retry logic bạn có thể thay đổi chúng để điều trị lỗi không 3960 giống như lỗi không 1205 và tự động thử lại ...

+0

Bạn tạo một điểm tốt .... ngoại trừ, tôi vẫn không hiểu tại sao có một chỉ số không nhóm, không duy nhất trên cột khóa ngoài của bảng có liên quan là đủ để làm điều này không xảy ra - nghĩa là không phải vậy rằng nó vẫn có thể thay đổi hành vi của chèn, ngay cả với chỉ mục? – Kram

+0

@Kram Tôi cho rằng chỉ mục giúp chi tiết. Động cơ biết một bảng phụ thuộc cần phải được khóa nhưng không có chỉ mục, nó có thể cố gắng khóa toàn bộ bảng thay vì một hàng duy nhất – jean

Các vấn đề liên quan