Nếu ai đó nói rằng không có NOLOCK, ứng dụng của họ luôn bị bế tắc, thì có (nhiều khả năng) có vấn đề với truy vấn của họ. bế tắc có nghĩa là hai giao dịch không thể tiến hành vì tranh chấp tài nguyên và vấn đề không thể giải quyết được. Ví dụ:
Xem xét giao dịch A và B. Cả hai đều đang trên chuyến bay. Giao dịch A đã chèn một hàng vào bảng X và Giao dịch B đã chèn một hàng vào bảng Y, do đó, Giao dịch A có khóa độc quyền trên X và Giao dịch B có khóa độc quyền trên Y.
Hiện tại, Giao dịch A cần chạy SELECT đối với bảng Y và giao dịch B cần chạy một lệnh SELECT đối với bảng X.
Hai giao dịch bị bế tắc: Một tài nguyên cần Y và B cần tài nguyên X. Vì giao dịch không thể tiến hành cho đến khi giao dịch khác hoàn thành giải quyết: không yêu cầu giao dịch cho một nguồn lực có thể được satisified cho đến khi giao dịch khác phát hành khóa của nó trên tài nguyên trong tranh chấp (hoặc bằng ROLLBACK hoặc COMMIT, không quan trọng.)
SQL Server xác định tình huống này và chọn một giao dịch hoặc giao dịch khác với tư cách là nạn nhân bế tắc, hủy bỏ giao dịch đó và quay lại, để giao dịch khác tự do tiến hành hoàn thành có thể đoán trước.
Rối khóa hiếm gặp trong đời thực (IMHO). Một chính càn chúng bằng cách
- đảm bảo rằng phạm vi giao dịch là càng nhỏ càng tốt, một cái gì đó SQL server không tự động (phạm vi giao dịch mặc định SQL Server là một tuyên bố duy nhất với một tiềm ẩn COMMIT), và
- đảm bảo rằng các nguồn lực giao dịch truy cập trong cùng một trình tự. Trong ví dụ trên, nếu giao dịch A và B cả hai tài nguyên bị khóa X và Y trong cùng một chuỗi, sẽ không có bế tắc.
Timeouts
Đã hết thời gian, mặt khác, xảy ra khi một giao dịch vượt quá thời gian chờ đợi của nó và được cuộn lại do tranh chấp tài nguyên. Ví dụ, Giao dịch A cần tài nguyên X. Tài nguyên X bị khóa bởi Giao dịch B, do đó, Giao dịch A chờ khóa được giải phóng. Nếu khóa không được giải phóng trong thời gian hết hạn của truy vấn, giao dịch chờ đợi sẽ bị hủy và được khôi phục. Mỗi truy vấn có thời gian chờ truy vấn liên kết với nó (giá trị mặc định là 30 giây, tôi tin), sau thời gian giao dịch bị hủy bỏ và được khôi phục. Thời gian chờ truy vấn có thể được đặt thành 0 giây, trong trường hợp đó SQL Server sẽ cho phép truy vấn chờ đợi mãi mãi.
Đây có thể là những gì họ đang nói đến. Theo kinh nghiệm của tôi, thời gian chờ như thế thường xảy ra trong cơ sở dữ liệu lớn khi công việc hàng loạt đang cập nhật hàng nghìn và hàng nghìn bản ghi trong một giao dịch duy nhất, mặc dù chúng có thể xảy ra do giao dịch kéo dài (kết nối với cơ sở dữ liệu sản xuất của bạn trong Query Abalyzer, thực thi BEGIN GIAO DỊCH, cập nhật một hàng trong bảng thường xuyên truy vấn trong Trình phân tích truy vấn và đi ăn trưa mà không thực thi ROLLBACK hoặc COMMIT TRANSACTION và xem mất bao lâu để các DBA sản xuất đi vượn ** t trên bạn.Đừng hỏi tôi làm thế nào tôi biết điều này)
loại này thời gian chờ thường là những gì dẫn đến đổ ra SQL một cách hoàn hảo vô tội với tất cả các loại NOLOCK gợi ý
[TIP: nếu bạn sẽ làm điều đó, chỉ cần thực thi SET GIAO DIỆN BẠC ĐỌC ĐỌC ĐƯỢC CHẤP NHẬN là câu lệnh đầu tiên trong thủ tục lưu trữ của bạn và đã thực hiện với nó.]
Vấn đề với cách tiếp cận này (NOLOCK/READ UNCOMMITTED) là bạn có thể đọc dữ liệu không được cam kết từ giao dịch khác: không đầy đủ hoặc có thể được khôi phục sau, vì vậy tính toàn vẹn dữ liệu của bạn bị bắt buộc. Bạn có thể gửi một hóa đơn dựa trên dữ liệu có mức độ bogosity cao.
Quy tắc chung của tôi là người ta nên tránh sử dụng các gợi ý bảng càng sâu càng tốt. Hãy để SQL Server và trình tối ưu hóa truy vấn của nó thực hiện công việc của họ.
Cách đúng để tránh loại sự cố này là tránh loại giao dịch (ví dụ: chèn một triệu hàng tại một ngã rẽ) gây ra sự cố. Chiến lược khóa ẩn trong cơ sở dữ liệu quan hệ SQL được thiết kế xung quanh các giao dịch nhỏ của phạm vi ngắn. Khóa phải nhỏ trong phạm vi và thời lượng ngắn. Hãy nghĩ "nhân viên ngân hàng cập nhật tài khoản séc của ai đó bằng khoản tiền gửi." như trường hợp sử dụng cơ bản. Thiết kế các quy trình của bạn để làm việc trong mô hình đó và bạn sẽ hạnh phúc hơn nhiều theo cách 'tròn.
Thay vì chèn một triệu hàng trong một câu lệnh chèn mondo, hãy thực hiện công việc theo các đoạn độc lập và cam kết từng đoạn độc lập. Nếu hàng triệu hàng của bạn bị chết sau khi xử lý 999.000 hàng, tất cả công việc đã hoàn thành sẽ bị mất (chưa kể rằng rollback có thể là ab * tch, và bảng vẫn bị khóa trong quá trình rollback.) Nếu bạn chèn hàng triệu hàng của 1000 hàng mỗi, cam kết sau mỗi khối, bạn tránh tranh chấp khóa gây ra deadlocks, như ổ khóa sẽ được thu được và phát hành và mọi thứ sẽ tiếp tục di chuyển. Nếu một cái gì đó đi về phía nam trong khối 999 của 1000 hàng, và giao dịch bị hủy bỏ và quay trở lại, bạn vẫn nhận được 998.000 hàng được chèn vào; bạn chỉ mất 1000 hàng công việc. Khởi động lại/Thử lại dễ dàng hơn nhiều.
Ngoài ra, khóa leo thang xảy ra trong các giao dịch lớn. Đối với hiệu quả, ổ khóa leo thang đến phạm vi lớn hơn và lớn hơn khi số lượng khóa được tổ chức bằng cách tăng giao dịch. Nếu một giao dịch đơn lẻ chèn/cập nhật/xóa một hàng duy nhất trong một bảng, tôi sẽ nhận được một khóa hàng. Tiếp tục thực hiện điều đó và khi số lượng khóa hàng được giữ bởi giao dịch đó với bảng đó đạt giá trị ngưỡng, SQL Server sẽ báo cáo chiến lược khóa: các khóa hàng sẽ được hợp nhất và chuyển đổi thành khóa trang số nhỏ hơn, do đó tăng phạm vi các ổ khóa được giữ. Từ thời điểm đó trở đi, một chèn/xóa/cập nhật của một hàng sẽ khóa trang đó trong bảng. Khi số lượng khóa trang được giữ lên giá trị ngưỡng của nó, khóa trang sẽ được củng cố lại và chiến lược khóa sẽ chuyển sang khóa bảng: giao dịch hiện khóa toàn bộ bảng và không ai khác có thể chơi cho đến khi giao dịch cam kết hoặc quay lại.
Cho dù bạn có thể tránh việc sử dụng chức năng NOLOCK/READ UNCOMMITTED hoàn toàn phụ thuộc vào bản chất của các quy trình đánh cơ sở dữ liệu bên dưới (và văn hóa của tổ chức sở hữu nó).
Bản thân tôi, tôi cố gắng tránh sử dụng càng nhiều càng tốt.
Hy vọng điều này sẽ hữu ích.
Với ảnh chụp nhanh hoạt động, cơ hội bạn gặp phải bế tắc là gì? Tôi sẽ không đề nghị rằng bạn có thể cho tôi một phần trăm, nhưng bạn đã bao giờ chạy vào bế tắc với nó đang chạy chưa? – Limey
Nó dường như đã cố định vấn đề StackOverflow, bản thân tôi đã không nhìn thấy deadlocks với nó, nhưng tôi cũng thực hiện một số thực hành tốt nhất về lập trình máy chủ SQL mà giảm thiểu điều này để bắt đầu với – SQLMenace
Không phải luôn luôn là một ý tưởng tốt ... http: // sqlblogcasts .com/blogs/tonyrogerson/archive/2006/11/16/1345.aspx – gbn