Biểu đồ khóa chết với khóa trên một chỉ mục trên bảng dường như không liên quan


7

Tôi có một biểu đồ bế tắc từ một bế tắc trong đó một quy trình đang thực hiện CHỌN và một quy trình đang thực hiện CẬP NHẬT. Điều này có vẻ giống như trường hợp cổ điển trong đó CHỌN có khóa NCI để thực hiện nối và sau đó khóa CI để lấy tất cả dữ liệu bằng cách tra cứu. Và CẬP NHẬT đang sử dụng khóa CI để thực hiện cập nhật và sau đó cần khóa NCI vì bản cập nhật dẫn đến thay đổi trạng thái và NCI tạo điều kiện tìm các mục theo trạng thái.

Vấn đề là một trong những khóa mà CẬP NHẬT muốn KHÔNG có trên bảng mà nó đang cập nhật và tôi không thể tìm thấy lý do tại sao điều này xảy ra.

Đây là CHỌN:

SELECT *,
       RIGHT(c.CC_NUMBER, 4) AS CC_LAST_4,
       DATEDIFF(ss, '1970-01-01', plan_started ) plan_started_epoch,
       DATEDIFF(ss, '1970-01-01', plan_expires ) plan_expires_epoch
FROM customers c, accounts a, parent_cos pc, htt_customers_overlay_ultra u
WHERE c.customer_id = a.customer_id
AND   u.customer_id = c.customer_id
AND   a.cos_id=pc.cos_id
AND   u.customer_id = 9300;

Đây là CẬP NHẬT:

UPDATE htt_customers_overlay_ultra SET plan_state = 'Active'  WHERE customer_id = 9300;

Nhưng theo biểu đồ khóa chết, CẬP NHẬT đang có được một khóa trên ACCOUNTS.ACCOUNT0, đó là PK (CI) của bảng TÀI KHOẢN. Không có khóa ngoại trong bảng lớp phủ. Có một số ràng buộc mặc định mà hiện tại tôi không có quyền xem.

Tôi đã xem biểu đồ khóa chết trong SSMS và trong SQL Sentry Plan Explorer Pro và không ai khôn ngoan hơn.

Dưới đây là các kế hoạch thực hiện:

Đối với CHỌN

Để cập nhật

Tôi muốn tìm hiểu lý do tại sao nó nhận được khóa này, và sau đó là cách tốt nhất để nối tiếp các cuộc gọi này.

Những điều tôi biết mà tôi đã tư vấn cho khách hàng đã mang khóa, nhưng không giải thích về khóa dường như không liên quan đang phát sinh:

Xóa * và xác định các cột cần thiết và thay đổi NCI để che phủ - điều này có khả năng khiến CHỌN sử dụng ít khóa hơn

Xác định lý do tại sao hệ thống CHỌN cùng một dữ liệu mà một quy trình khác đang xử lý - điều này có khả năng giảm thiểu hai quá trình này đang chạy cùng một lúc

Có một bảng quét trong CHỌN


Có thể truy vấn cập nhật đã có được Xkhóa khóa trên "dbo.ACCOUNTS" từ một tuyên bố trước đó trong cùng một giao dịch không được hiển thị trong biểu đồ?
Martin Smith

Nếu tôi đọc đồ thị đúng, SELECTcó một Ukhóa trên chỉ số PK của htt_customers_overlay_ultra- tại sao? Quá trình đó có 0 log được sử dụng.
Jon Seigel

@JonSeigel - Không có bản cập nhật ( process589f948) nào có Ukhóa và đang cố chuyển đổi nó thành Xkhóa nhưng bị chặn bởi một Skhóa được giữ bởi SELECT( process5240988)
Martin Smith

@Cade Roux: Giả sử Martin Smith đã tìm ra thủ phạm, tôi đoán cách dễ nhất để tránh những vấn đề như vậy là kích hoạt read_committed_snapshotdb.
a1ex07

Các lựa chọn được ban hành bởi các UDF vô hướng giữ các khóa, nhưng không hiển thị trong các kế hoạch thực hiện. Có lẽ bản cập nhật của bạn kích hoạt một trình kích hoạt sử dụng UDF vô hướng?
AK

Câu trả lời:


6

Các UPDATEtruy vấn có một Xkhóa trên một phím trên "dbo.ACCOUNTS" chặn SELECTtừ nhận được một Skhóa.

Các SELECTtruy vấn có một Skhóa trên một khóa của htt_customers_overlay_ultra. Các UPDATEtruy vấn có một Ukhóa trên cùng một phím và bị chặn cố gắng để chuyển đổi đó để một Xkhóa.

Kế hoạch thực hiện cho UPDATEtính năng hoàn toàn không có tính năng này Accountsvì vậy không có lý do rõ ràng nào để nó có khóa phím Accounts. Giao dịch Cập nhật bắt đầu 0.01vài giây trước khi lô đó thực hiện. 2013-01-13 08:49:30.213vs 2013-01-13 08:49:30.223.

Có lẽ đã có một tuyên bố trước đó trong một đợt khác (do đó không được hiển thị trong biểu đồ khóa chết) thực sự bắt đầu giao dịch và có được Xkhóa bí ẩn .


Tôi tin rằng tất cả mã của họ là các giao dịch ngầm trong các lô adhoc duy nhất được tạo bởi PHP. Tôi nghĩ rằng phải có một số ràng buộc khác, nhưng tôi không thấy bất kỳ khóa ngoại nào. Có một số ràng buộc mặc định mà tôi đang cố gắng để có được các định nghĩa cho,
Cade Roux

@CadeRoux - Làm thế nào để giao dịch có thể bắt đầu trước đợt đó? Nếu UPDATEđến htt_customers_overlay_ultratrước đây được cập nhật Accountstrong cùng một giao dịch nó sẽ tất nhiên giải thích nó (mặc dù nó đã có thể cần thiết để có một bản cập nhật cập nhật không như đăng nhập sử dụng = 0) hoặc có thể là một SELECTvới một rõ ràng XLOCKgợi ý.
Martin Smith

Tôi không nghĩ họ đang thực hiện bất kỳ giao dịch nào - Tôi nghĩ rằng hai truy vấn này được thực hiện đồng thời từ các phần khác nhau của ứng dụng (có vẻ kỳ lạ vì cả hai đều bị giới hạn trong một tài khoản - hoặc có lẽ đó là nhiều thành phần của cùng một trang tải không đồng bộ với nhiều yêu cầu) và chúng không đủ may mắn (hoặc có lẽ nó phổ biến vì bài đăng của thay đổi đang chạy đồng thời với việc tải dữ liệu trên tài khoản cho một phần khác của trang) đến bế tắc.
Cade Roux

2
@Martin Smith: Lời giải thích của bạn có vẻ rất hợp lý với tôi. Một điều nữa có lẽ chứng minh câu trả lời của bạn - trong kết xuất cho truy vấn thứ hai (cập nhật) trancount="2". Tôi tin rằng điều đó có nghĩa là có 2 begin transaction... Điều đó có thể giải thích tại sao bãi rác không có update accounts...
a1ex07

@ a1ex07 - Phát hiện tốt. Nếu @@trancount = 2phải rõ ràng begin tranở đâu đó AFAIK.
Martin Smith
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.