2009-06-25 23 views
7

Tôi là thành viên của nhóm xây dựng một trang web dựa trên ADO.NET. Đôi khi chúng tôi có một số nhà phát triển và một công cụ kiểm tra tự động làm việc đồng thời một bản sao phát triển của cơ sở dữ liệu.Sử dụng IsolationLevel.Snapshot nhưng DB vẫn đang khóa

Chúng tôi sử dụng mức cô lập ảnh chụp, theo hiểu biết tốt nhất của tôi, sử dụng đồng thời lạc quan: thay vì khóa, nó hy vọng điều tốt nhất và ném ngoại lệ nếu bạn cố gắng thực hiện giao dịch nếu các hàng bị ảnh hưởng bị thay đổi bởi một bên khác trong quá trình giao dịch.

Để sử dụng mức cô lập ảnh chụp chúng tôi sử dụng:

ALTER DATABASE <database name> 
SET ALLOW_SNAPSHOT_ISOLATION ON; 

và trong C#:

Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot); 

Lưu ý rằng IsolationLevel Snapshot là không giống như ReadCommitted Snapshot, mà chúng tôi cũng đã cố gắng, nhưng hiện không sử dụng.

Khi một trong các nhà phát triển chuyển sang chế độ gỡ lỗi và tạm dừng ứng dụng .NET, họ sẽ giữ kết nối với một giao dịch đang hoạt động trong khi gỡ lỗi. Bây giờ, tôi cho rằng đây không phải là vấn đề - sau tất cả, tất cả giao dịch đang sử dụng mức cô lập ảnh chụp, vì vậy trong khi một giao dịch bị tạm dừng, các giao dịch khác sẽ có thể tiến hành bình thường vì giao dịch bị tạm dừng không giữ bất kỳ khóa nào. Tất nhiên, khi giao dịch bị tạm dừng hoàn tất, nó có khả năng phát hiện xung đột; nhưng đó là chấp nhận được miễn là các nhà phát triển khác và các thử nghiệm tự động có thể tiến hành không bị cản trở. Tuy nhiên, trên thực tế, khi một người dừng giao dịch trong khi gỡ lỗi, tất cả người dùng DB khác cố truy cập vào cùng một hàng đều bị chặn mặc dù sử dụng mức cô lập ảnh chụp nhanh.

Không ai biết tại sao điều này xảy ra và/hoặc làm cách nào để tôi có thể đạt được sự đồng thời thực sự lạc quan (không chặn)?

Độ phân giải (một điều không may đối với tôi): Remus Rusanu lưu ý rằng người viết luôn chặn các nhà văn khác; điều này được sao lưu bởi MSDN - nó không hoàn toàn xuất hiện và nói như vậy, nhưng chỉ bao giờ đề cập đến việc tránh khóa người đọc. Tóm lại, hành vi tôi muốn không được thực hiện trong SQL Server.

Trả lời

8

SNAPSHOT cô lập mức độ ảnh hưởng, giống như tất cả các mức cô lập, chỉ đọc. Viết vẫn đang chặn nhau. Nếu bạn tin rằng những gì bạn nhìn thấy là khối đọc, thì bạn nên điều tra thêm và kiểm tra các loại tài nguyên và tên tài nguyên mà việc chặn xảy ra (wait_type và wait_resource trong sys.dm_exec_requests).

Tôi sẽ không tư vấn khi thực hiện thay đổi mã để hỗ trợ kịch bản liên quan đến nhà phát triển đang xem xét trình gỡ lỗi trong vài phút khi kết thúc. Nếu bạn tin rằng kịch bản này có thể lặp lại trong sản xuất (ví dụ như khách hàng bị treo) thì đó là một câu chuyện khác. Để đạt được những gì bạn muốn, bạn phải giảm thiểu viết và thực hiện tất cả ghi vào cuối giao dịch, trong một cuộc gọi duy nhất cam kết trước khi trở về. Bằng cách này, không khách hàng nào có thể giữ khóa X trong một thời gian dài (không thể treo trong khi giữ khóa X). Trong thực tế điều này là khá khó khăn để kéo ra và đòi hỏi rất nhiều kỷ luật về một phần của các nhà phát triển trong cách họ viết mã truy cập dữ liệu.

+0

Hành vi này khó xảy ra. Mặt khác, phiên bản phát triển khá quan trọng và tôi sẵn sàng thực hiện thay đổi mã nếu điều đó phát triển. Thật không may, một phong cách "svn-esque" của khóa (hy vọng cho tốt nhất và chỉ đơn giản là thất bại về xung đột) dường như không được thực hiện. Khả năng có các giao dịch dài và phức tạp mà không chặn tất cả các giao dịch nhỏ vẫn hữu ích - như vậy, chúng tôi sử dụng ít giao dịch lý tưởng hơn để tránh bị chặn. –

+1

Không có viên đạn bạc. Nhưng nếu bạn thấy urself thường bị chặn trong viết vs viết, bạn nên xem xét lý do tại sao điều này xảy ra, tại sao khác nhau 'yêu cầu' gây ra các bản cập nhật của cùng một dữ liệu. Có lẽ bạn có thể phân vùng ứng dụng của bạn tốt hơn, giảm xác suất chồng chéo. Có lẽ một số cập nhật có thể được hoãn lại, enqueued trong một bảng làm việc trong giao dịch người dùng (enque/dequeue có thể được thực hiện khối miễn phí, cẩn thận) và sau đó được xử lý bởi các quy trình chuyên dụng. Cũng đảm bảo tất cả các giao dịch chỉ khóa tối thiểu cần thiết (không có khóa trang/bảng, không leo thang, không quét bảng vô ích). –

2

Bạn đã xem xét khóa khi một nhà phát triển tạm dừng giao dịch? Ngoài ra, chỉ cần bật mức cô lập ảnh chụp nhanh không có nhiều hiệu ứng. Bạn đã đặt ALLOW_SNAPSHOT_ISOLATION ON chưa?

Sau đây là các bước sau:

ALTER DATABASE <databasename> 
SET READ_COMMITTED_SNAPSHOT ON; 
GO 

ALTER DATABASE <database name> 
SET ALLOW_SNAPSHOT_ISOLATION ON; 
GO 

Sau khi cơ sở dữ liệu đã được kích hoạt cho ảnh chụp cô lập, các nhà phát triển và sau đó người dùng phải yêu cầu giao dịch của họ được chạy trong chế độ chụp này. Điều này phải được thực hiện trước khi bắt đầu giao dịch, hoặc bằng một chỉ thị client-side trên đối tượng giao dịch ADO.NET hoặc trong truy vấn Transact-SQL của họ bằng cách sử dụng câu lệnh sau:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT 

Raj

+0

Cơ sở dữ liệu đã bật allow_snapshot_isolation. Không làm như vậy dẫn đến một ngoại lệ ngay lập tức; bạn không thể đặt isolationlevel thành snapshot khi allow_snapshot_isolation bị tắt (tức là thiết lập mức cách ly không thất bại). Tôi sẽ cập nhật bài đăng để phản ánh các lệnh chính xác cần thiết, cảm ơn! –

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