Câu hỏi Nguyên nhân của quá trình là nạn nhân bế tắc


Tôi có một quá trình với một Chọn mất một thời gian dài để hoàn thành, theo thứ tự từ 5 đến 10 phút.
Tôi hiện không sử dụng NOLOCK làm gợi ý cho cơ sở dữ liệu MS SQL.
Đồng thời chúng tôi có một quá trình khác làm cập nhật và chèn vào cùng một cơ sở dữ liệu và cùng một bảng.
 Quá trình đầu tiên đã bắt đầu, gần đây kết thúc sớm với một thông điệp

SQLEXCEPTION: Giao dịch bị bế tắc trên các tài nguyên khóa với một tiến trình khác và đã được chọn làm nạn nhân bế tắc.

Quá trình đầu tiên này đang chạy ở các trang khác trong điều kiện giống nhau nhưng với cơ sở dữ liệu nhỏ hơn và do đó câu lệnh chọn được đề cập mất một khoảng thời gian ngắn hơn nhiều (theo thứ tự 30 giây hoặc lâu hơn). Trong các trang web khác, tôi không nhận được thông báo bế tắc trong các trang web khác này. Tôi cũng không nhận được thông báo này tại trang web có vấn đề ban đầu, nhưng, tôi cho rằng, khi cơ sở dữ liệu đã phát triển, tôi tin rằng tôi phải vượt qua một số ngưỡng. Dưới đây là câu hỏi của tôi:

  1. Có thể mất thời gian cho một giao dịch để thực hiện khiến cho quy trình được liên kết có nhiều khả năng bị gắn cờ hơn như một nạn nhân bế tắc.
  2. Nếu tôi thực hiện lựa chọn với gợi ý NOLOCK, điều này sẽ loại bỏ vấn đề?
  3. Tôi nghi ngờ rằng một trường datetime được kiểm tra như là một phần của mệnh đề WHERE trong câu lệnh select là gây ra thời gian tra cứu chậm. Tôi có thể tạo chỉ mục dựa trên trường này không? Nó có được khuyến khích không?

76
2017-12-05 18:52


gốc


Câu trả lời một phần cho điểm 1: Đừng nhầm lẫn giữa bế tắc với thời gian chờ. Nếu bạn đang phải chịu một thời gian chờ thì thời gian liên quan đến việc hoàn thành một giao dịch có thể phải chịu trách nhiệm cho một giao dịch khác. Ngoài ra, nó sẽ là hữu ích để biết những gì tài nguyên bạn đang bế tắc trên (là nó một chỉ số hoặc một bảng?). - NealB
SET DEADLOCK_PRIORITY HIGH ALTER DATABASE dbname SET MULTI_USER; - gstackoverflow


Các câu trả lời:


Q1: Có thể mất thời gian cho một giao dịch để thực hiện khiến quá trình liên kết có nhiều khả năng bị gắn cờ hơn như một nạn nhân bế tắc.

Không. SELECT là nạn nhân bởi vì nó chỉ đọc dữ liệu, do đó giao dịch có chi phí thấp hơn liên kết với nó để được chọn là nạn nhân:

Theo mặc định, Database Engine chọn làm nạn nhân bế tắc   phiên chạy giao dịch ít tốn kém nhất để quay trở lại.   Ngoài ra, người dùng có thể chỉ định mức độ ưu tiên của phiên trong   tình trạng bế tắc bằng cách sử dụng SET DEADLOCK_PRIORITY tuyên bố.   DEADLOCK_PRIORITY có thể được đặt thành LOW, NORMAL hoặc HIGH hoặc theo cách khác   có thể được đặt thành bất kỳ giá trị nguyên nào trong phạm vi (-10 đến 10).

Q2. Nếu tôi thực hiện lựa chọn với gợi ý NOLOCK, điều này sẽ loại bỏ vấn đề?

Không. Vì nhiều lý do:

Q3. Tôi nghi ngờ rằng một trường datetime được kiểm tra như là một phần của mệnh đề WHERE trong câu lệnh select là gây ra thời gian tra cứu chậm. Tôi có thể tạo chỉ mục dựa trên trường này không? Nó có được khuyến khích không?

Có lẽ. Nguyên nhân gây ra bế tắc gần như rất có thể là một cơ sở dữ liệu được lập chỉ mục kém 10 phút truy vấn được chấp nhận trong các điều kiện hẹp như vậy, rằng tôi chắc chắn 100% trong trường hợp của bạn là không phải chấp nhận được.

Với sự tự tin 99%, tôi tuyên bố rằng bế tắc của bạn bị chặn bởi một bản quét bảng lớn xung đột với các bản cập nhật. Bắt đầu bằng cách chụp biểu đồ bế tắc để phân tích nguyên nhân. Bạn rất có thể sẽ phải tối ưu hóa lược đồ cơ sở dữ liệu của bạn. Trước khi bạn thực hiện bất kỳ sửa đổi nào, hãy đọc chủ đề này Chỉ mục thiết kế và các bài viết phụ.


96
2017-12-05 19:13



Cảm ơn bạn đã trả lời kỹ lưỡng của bạn. Tôi đoán tôi vẫn có một câu hỏi. Tại sao tôi sẽ nhận được tình trạng bế tắc chỉ trong một môi trường và không phải là một môi trường khác. Mặc dù phần mềm là như nhau. Câu trả lời của bạn cho thấy rằng khoảng thời gian chạy truy vấn Chọn không tạo ra sự khác biệt và thực tế là nó là một truy vấn Chọn mỗi lần khiến quá trình thất bại. Nhưng sau đó, tại sao chỉ khi truy vấn chọn mất một thời gian dài để thực thi? - Elliott
Độ dài của truy vấn không tạo sự khác biệt trong chọn nạn nhân bế tắc. Nó tạo sự khác biệt trong việc gây ra bế tắc bởi ít nhất hai yếu tố: 1) xác suất đơn giản. Truy vấn càng dài, có nhiều khả năng chồng lấp các cập nhật đồng thời và chạy vào các deadlock. 2) một bảng lớn hơn có thể sử dụng một kế hoạch truy vấn hoàn toàn khác, một trong đó là dễ bị deadlocks. - Remus Rusanu


Đây là vấn đề bế tắc cụ thể thực sự xảy ra như thế nào và nó đã thực sự được giải quyết như thế nào. Đây là một cơ sở dữ liệu khá tích cực với 130 nghìn giao dịch diễn ra hàng ngày. Các chỉ mục trong các bảng trong cơ sở dữ liệu này ban đầu được nhóm lại. Khách hàng yêu cầu chúng tôi làm cho các chỉ mục không được phân bổ. Ngay khi chúng tôi làm vậy, bế tắc bắt đầu. Khi chúng tôi thiết lập lại các chỉ mục như được nhóm lại, bế tắc dừng lại.


9
2017-12-14 22:54



Ai đó có thể giải thích tại sao? (Các giải pháp ma thuật không phải là rất hữu ích) - OGrandeDiEnne


Câu trả lời ở đây đáng để thử nhưng bạn cũng nên xem lại mã của mình. Cụ thể có một đọc về câu trả lời của Polyfun ở đây: Làm thế nào để thoát khỏi bế tắc trong một ứng dụng SQL Server 2005 và C #?

Nó giải thích vấn đề tương tranh và cách sử dụng "with (updlock)" trong truy vấn của bạn có thể sửa tình trạng bế tắc của bạn - tùy thuộc vào chính xác mã của bạn đang làm gì. Nếu mã của bạn không tuân theo mẫu này, đây có thể là cách khắc phục tốt hơn, trước khi sử dụng để đọc sách bẩn, v.v.


2
2017-09-28 05:14