2013-07-04 93 views
1

我正試圖解決涉及我們繁忙的表之一的死鎖的錯誤。我讀過關於死鎖的this SO question,雖然它很有意義,但查詢順序似乎不是我的原因。具有相同查詢的死鎖

這裏是SHOW ENGINE INNODB STATUS;的縮略的輸出:

*** (1) TRANSACTION: 
TRANSACTION 1 2611184895, ACTIVE 0 sec, process no 17501, OS thread id 140516779579136 starting index read 
mysql tables in use 1, locked 1 
LOCK WAIT 2 lock struct(s), heap size 368, 1 row lock(s) 
MySQL thread id 211935717, query id 3146186174 [SERVER A] Searching rows for update 

UPDATE images_unread_comments 
    SET unread = 0 
    WHERE user_id = 1 AND comment_id IN(1,2,3) AND unread = 1 

*** (1) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 0 page no 404976 n bits 632 index `users_unread_comments` of table images_unread_comments trx id 1 2611184895 lock_mode X waiting 
Record lock, heap no 558 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 0001461a; asc F ;; 1: len 1; hex 01; asc ;; 2: len 6; hex 00000e67d888; asc g ;; 

*** (2) TRANSACTION: 
TRANSACTION 1 2611184892, ACTIVE 0 sec, process no 17501, OS thread id 140516774520576 updating or deleting, thread declared inside InnoDB 494 
mysql tables in use 1, locked 1 
6 lock struct(s), heap size 1216, 11 row lock(s), undo log entries 1 
MySQL thread id 211935715, query id 3146186169 [SERVER B] Updating 

UPDATE images_unread_comments 
    SET unread = 0 
    WHERE user_id = 1 AND comment_id IN(1,2,3) AND unread = 1 
    *** (2) HOLDS THE LOCK(S): 
RECORD LOCKS space id 0 page no 404976 n bits 632 index users_unread_comments of table images_unread_comments trx id 1 2611184892 lock_mode X 
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0 
0: len 8; hex 73757072656d756d; asc supremum;; 

Record lock, heap no 555 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 
0: len 4; hex 0001461a; asc F ;; 1: len 1; hex 01; asc ;; 2: len 6; hex 00000e67daf0; asc g ;; 

Record lock, heap no 556 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 
0: len 4; hex 0001461a; asc F ;; 1: len 1; hex 01; asc ;; 2: len 6; hex 00000e67dadb; asc g ;; 

Record lock, heap no 557 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 
0: len 4; hex 0001461a; asc F ;; 1: len 1; hex 01; asc ;; 2: len 6; hex 00000e67d940; asc g @;; 

Record lock, heap no 558 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 0001461a; asc F ;; 1: len 1; hex 01; asc ;; 2: len 6; hex 00000e67d888; asc g ;; 

*** (2) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 0 page no 404976 n bits 632 index users_unread_comments of table images_unread_comments trx id 1 2611184892 lock_mode X locks gap before rec insert intention waiting 
Record lock, heap no 558 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 0001461a; asc F ;; 1: len 1; hex 01; asc ;; 2: len 6; hex 00000e67d888; asc g ;; 

*** WE ROLL BACK TRANSACTION (1) 

我注意到的事情是兩個SQL語句是相同的;但是一個正在服務器A上執行,另一個正在服務器B上執行。不管爲什麼會發生這種情況 - 如果兩個查詢都以相同順序鎖定相同的密鑰,爲什麼會造成死鎖?還是我首先誤解了僵局?

+0

在另一個查詢(在一個或兩個線程中)之前運行的另一個查詢很可能已鎖定某些行。此外,您還會縮短狀態報告的時間 - 第二個等待的事務和它持有的鎖定是什麼? – Vatev

+0

@Vatev我已經將該部分的其餘部分添加到輸出中。 – Graham

+0

我應該注意到這是第一次...鎖在另一張桌子上(images_unread_comments)。是否有與這兩個表相關的觸發器或外鍵? – Vatev

回答

0

看來,事務1已經執行了另一個操作(插入?),其中它鎖定了索引中的間隙。它比等待事務2執行更新,因爲2已經鎖定了ID爲1的記錄。但事務2無法繼續,因爲事務1對索引持有鎖。如果可以通過此操作隔離事務中使用的所有SQL語句,我們可以看到造成死鎖的確切原因