2010-01-20 42 views
10

Ai đó có thể giúp tôi bế tắc trong SQL Server 2005 không?Bối cảnh SQL Server 2005 bế tắc với chỉ số không độc quyền

Để kiểm tra đơn giản, tôi có một bảng "Sách" có khóa chính (id) và tên cột. Chỉ mục mặc định của khóa chính này là nonclustered.

Bế tắc xảy ra khi hai phiên chạy cùng một lúc. Màn hình hoạt động cho thấy phiên đầu tiên "// bước 1" khóa hàng (thoát khóa) bằng khóa X. Phiên thứ hai giữ hàng U khóa và khóa U khóa. Hình ảnh bế tắc hiển thị "// step2" của phiên đầu tiên yêu cầu khóa U chính.

Nếu chỉ mục là được nhóm, không có bế tắc trong trường hợp này. "// step 1" sẽ giữ cho hàng và khóa phím cùng một lúc, do đó, không có vấn đề gì. Tôi có thể hiểu việc khóa một hàng cũng sẽ khóa chỉ mục vì nút lá của chỉ số nhóm là dữ liệu hàng.

Nhưng tại sao nonclustered chỉ mục theo cách này? Nếu phiên thứ hai giữ khóa U khóa, tại sao "bước 1" của phiên đầu tiên không giữ khóa này vì chúng giống như câu lệnh cập nhật.

--// first session 
BEGIN TRAN 
    update Book set name = name where id = 1 //step 1 
    WaitFor Delay '00:00:20' 
    update Book set name = 'trans' where id = 1 //step2 
COMMIT 

--// second session 
BEGIN TRAN 
--// this statement will keep both RID(U lock) and KEY(U lock) if first session did not use HOLDLOCK 
    update Book set name = name where id = 1 
COMMIT 
+0

bạn có khóa cụm trên bảng Sách mẫu không? Tôi không nghĩ rằng đó là câu hỏi liệu PK của bạn có được phân nhóm hay không - tôi nghĩ nó còn quan trọng hơn nếu bạn thực sự có một Clustered Key (và do đó một bảng được nhóm), hoặc cho dù bạn đang xử lý một heap (không có chỉ mục clustered)) –

+0

Bạn có thể thêm đầu ra liên quan của 'exec sp_lock' trong khi nó đang bế tắc không? – Andomar

+0

Từ sqlprofiler, hình ảnh bế tắc hiển thị "// step2" của phiên đầu tiên yêu cầu khóa U chính, nhưng nó được tổ chức bởi seesion2. –

Trả lời

10

Yếu tố liên quan ở đây là bạn đang sử dụng cột trong mệnh đề where của bạn có chỉ mục không được chỉ định. Khi SQL Server xử lý một bản cập nhật, nó đi một cái gì đó như thế này:

  1. Tìm hàng để cập nhật, lấy U ổ khóa trên dữ liệu chạm
  2. Cập nhật hàng, lấy ổ khóa X trên dữ liệu sửa đổi

Sau tuyên bố hoàn thành (theo mặc định READ COMMITTED cách ly), các khóa U được giải phóng nhưng các khóa X được giữ cho đến khi kết thúc giao dịch để duy trì sự cô lập.

Trong trường hợp chỉ mục nonclustered của bạn, SQL Server tìm kiếm chỉ mục trên id và sử dụng điều này để tra cứu hàng thực tế.Các khóa diễn ra như thế này:

  1. (Phần 1, bước 1) U khóa đưa vào chỉ số giá trị quan trọng đối với id = 1
  2. (Phiên 1, bước 1) khóa X đưa vào RID cho hàng với id = 1
  3. (phiên 1, bước 1) U lock phát hành
  4. (Phần 2) U khóa đưa vào chỉ số giá trị quan trọng đối với id = 1
  5. (Phần 2) khóa X bị chặn cho RID cho hàng với id = 1
  6. (Phiên 1, bước 2) Khóa U bị chặn trên giá trị khóa chỉ mục cho id = 1 - DEADLOCK

Tuy nhiên, khi chỉ mục là chỉ mục nhóm, không có bước riêng biệt để chuyển khóa chỉ mục thành hàng - giá trị chỉ mục nhóm số nhận dạng hàng. Do đó, khóa kết thúc như thế này:

  1. (Phần 1, bước 1) U khóa đưa vào chỉ số giá trị quan trọng đối với id = 1
  2. (Phiên 1, bước 1) U lock nâng cấp lên X khóa
  3. (Phần 2) U khóa chặn trên chỉ số giá trị quan trọng đối với id = 1
  4. (phiên 1, bước 2) khóa đã được tổ chức vào chỉ số giá trị quan trọng đối với id = 1
  5. (phiên 1, cam kết) lock phát hành
  6. (Phiên 2) Khóa U được cấp
  7. (Phần 2) U lock nâng cấp lên khóa X
  8. (Phần 2) khóa phát hành

Như mọi khi, hãy ghi nhớ rằng trong khi điều này có thể là kế hoạch truy vấn được sử dụng trong trường hợp này, tôi ưu hoa được tự do làm mọi thứ khác đi. Ví dụ, nó có thể chọn một bảng quét hoặc để đưa ra các khóa chặt chẽ hơn. Trong những trường hợp này, bế tắc có thể không xảy ra.

+0

Cảm ơn bạn rất nhiều, nó có ý nghĩa với tôi. Vấn đề có vẻ là "bước riêng biệt để chuyển đổi khóa chỉ mục thành hàng" trong chỉ mục nonclustered. –

+0

Nếu tôi thêm dấu móc khóa gợi ý trong câu lệnh cập nhật cho cả hai phiên, điều này được giải quyết vì khóa U và X vẫn được giữ trong phiên 1. Hiểu biết của tôi là yêu cầu duy nhất khóa S, tôi tự hỏi tại sao holdlock có thể cho phép phiên 1 giữ U khóa cho khóa và khóa X cho RID? Cảm ơn bạn. –

+0

Có thể bế tắc gây ra các sự cố tiềm ẩn khác (nghĩa là một bế tắc khác, hạ cấp hiệu suất)? –

0

Liên kết này có nhiều đề xuất hữu ích: SQL Server deadlocks between select/update or multiple selects.

Dưới đây là một số điểm cần xem xét có thể giúp mọi người trả lời câu hỏi của bạn:

  1. giao dịch gì cô lập mức độ bạn đang sử dụng?
  2. Khóa leo thang (ví dụ: từ hàng này sang trang khác) có được phép không?
  3. Có chỉ mục nào trên cột 'tên' không?
+0

1.read comitted 2.sử dụng cài đặt mặc định bằng SQLServer 3.Không có chỉ mục nào khác. –

0

cập nhật đầu tiên của bạn không thực sự thay đổi bất cứ điều gì:

update Book set name = name where id = 1 

Thy một lệnh mà thực sự thay đổi cột của bạn, sau đó một khóa độc quyền sẽ được tổ chức vào ngày liên tiếp.

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