Nguyên nhân của một quy trình là một nạn nhân bế tắc


105

Tôi có một quy trình với Lựa chọn mất nhiều thời gian để hoàn thành, theo thứ tự từ 5 đến 10 phút.
Tôi hiện không sử dụng NOLOCK như một gợi ý cho công cụ cơ sở dữ liệu MS SQL.
Đồng thời, chúng tôi có một quy trình khác thực hiện 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 báo

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

Quá trình đầu tiên này đang chạy ở các trang web khác trong điều kiện giống hệt nhau nhưng với cơ sở dữ liệu nhỏ hơn và do đó câu lệnh select đượ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 này, 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 đang gặp sự cố ban đầu, nhưng, tôi cho rằng, khi cơ sở dữ liệu đã phát triển, tôi tin rằng mình phải vượt qua ngưỡng nào đó. Đây là những câu hỏi của tôi:

  1. Có thể thời gian cần thiết để thực hiện một giao dịch làm cho quá trình liên quan có nhiều khả năng bị gắn cờ là nạn nhân của deadlock hay không.
  2. Nếu tôi thực hiện lựa chọn với gợi ý NOLOCK, điều này có loại bỏ được vấn đề không?
  3. Tôi nghi ngờ rằng trường datetime được kiểm tra như một phần của mệnh đề WHERE trong câu lệnh select đang 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â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 bị hế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ể chịu trách nhiệm cho việc tiếp tục giao dịch khác. Ngoài ra, sẽ rất hữu ích nếu biết bạn đang sử dụng tài nguyên nào (nó là một chỉ mục hay một bảng?).
NealB

1
SET DEADLOCK_PRIORITY HIGH ALTER DATABASE dbname SET MULTI_USER;
gstackoverflow

Câu trả lời:


128

Câu hỏi 1: Có thể thời gian cần thiết để thực hiện một giao dịch làm cho quá trình liên quan có nhiều khả năng bị gắn cờ là nạn nhân của deadlock.

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

Theo mặc định, Công cụ cơ sở dữ liệu chọn làm nạn nhân của bế tắc phiên đang chạy giao dịch ít tốn kém nhất để khôi phục . Ngoài ra, người dùng có thể chỉ định mức độ ưu tiên của các phiên trong tình huống bế tắc bằng cách sử dụng SET DEADLOCK_PRIORITYcâu lệnh. DEADLOCK_PRIORITY có thể được đặt thành THẤP, BÌNH THƯỜNG hoặc CAO hoặc cách khác có thể được đặt thành bất kỳ giá trị số nguyên nào trong phạm vi (-10 đến 10).

Quý 2. Nếu tôi thực hiện lựa chọn với gợi ý NOLOCK, điều này có loại bỏ được vấn đề không?

Không. Vì một số lý do:

Q3. Tôi nghi ngờ rằng trường datetime được kiểm tra như một phần của mệnh đề WHERE trong câu lệnh select đang 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 của bế tắc gần như rất có thể là do cơ sở dữ liệu được lập chỉ mục kém. 10 phút truy vấn có thể chấp nhận được trong điều kiện hạn hẹp như vậy, mà tôi chắc chắn 100% trong trường hợp của bạn là không thể chấp nhận được.

Với độ tin cậy 99%, tôi tuyên bố rằng bế tắc của bạn được giải quyết bằng cách 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ủa cơ sở dữ liệu của mình. Trước khi bạn thực hiện bất kỳ sửa đổi nào, hãy đọc chủ đề Thiết kế chỉ mục này và các bài viết phụ.


Cảm ơn bạn đã trả lời cặn kẽ. Tôi đoán tôi vẫn còn một câu hỏi. Tại sao tôi lại gặp phải tình huống bế tắc chỉ trong một môi trường mà không phải môi trường khác. Mặc dù phần mềm giống nhau. Câu trả lời của bạn gợi ý 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à chính một truy vấn Chọn đang khiến quá trình không thành công. Nhưng sau đó, tại sao chỉ khi truy vấn chọn mất nhiều thời gian để thực thi?
Elliott

4
Độ dài của truy vấn không tạo ra sự khác biệt trong việc chọn nạn nhân của deadlock . Nó tạo ra 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àng có nhiều khả năng chồng chéo các bản cập nhật đồng thời và rơi vào bế tắc. 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 kế hoạch dễ bị bế tắc.
Remus Rusanu

12

Đây là cách vấn đề bế tắc cụ thể này thực sự xảy ra và cách nó thực sự được giải quyết. Đây là một cơ sở dữ liệu khá hoạt động 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 bị phân biệt. Ngay sau khi chúng tôi làm vậy, sự 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, quá trình deadlock đã dừng lại.


34
Ai đó có thể giải thích tại sao? (Giải pháp Magic không phải là rất hữu ích)
OGrandeDiEnne

1
Anh chàng này giải thích điều đó trong bài đăng của anh ấy: mssqltips.com/sqlservertip/2517/…
siga0984

6

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

Nó giải thích vấn đề đồng thời và cách sử dụng "with (updlock)" trong các truy vấn của bạn có thể khắc phục tình trạng bế tắc của bạn - thực sự 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 tuân theo mẫu này, đây có thể là một bản sửa lỗi tốt hơn để thực hiện, trước khi sử dụng đến các lần đọc bẩn, v.v.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.