2013-07-04 5 views
1

J'essaie de résoudre une erreur impliquant des blocages sur l'une de nos tables occupées. J'ai lu this SO question sur les blocages et bien que cela ait un sens, l'ordre de requête ne semble pas être la cause dans mon cas.Impasse avec des requêtes identiques

est ici la sortie abrégée de 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) 

La chose que je remarque est que les deux instructions SQL sont identiques; Cependant, l'un est en cours d'exécution sur le serveur A et l'autre sur le serveur B. Indépendamment de la raison pour laquelle cela se produit, pourquoi créer un blocage si les deux requêtes verrouillent les mêmes clés dans le même ordre? Ou est-ce que je ne comprends pas la caste des blocages en premier lieu?

+0

Il est probable qu'une autre requête qui s'exécute avant celle-ci (dans un ou les deux threads) ait verrouillé lignes En outre, vous réduisez un peu le rapport d'état: que réserve la deuxième transaction et quel verrou tient-elle? – Vatev

+0

@Vatev J'ai ajouté le reste de cette section à la sortie. – Graham

+0

Je devrais remarquer cela la 1ère fois ... Les verrous sont sur une autre table (images_unread_comments). Y a-t-il des déclencheurs ou des clés étrangères liées aux 2 tables? – Vatev

Répondre

0

Il semble que la transaction 1 ait effectué une autre opération (insérer?) Dans laquelle elle a bloqué un intervalle dans l'index. Il attend que la transaction 2 effectue la mise à jour, puisque 2 a verrouillé l'enregistrement avec l'ID 1. La transaction 2 ne peut cependant pas continuer car la transaction 1 maintient un verrou sur l'index. Si vous pouvez isoler toutes les instructions SQL utilisées dans une transaction par cette opération, nous pouvons voir la raison exacte de l'interblocage