2010-10-21 25 views
4

J'ai une question à propos de MySQL InnoDB. Par exemple: Je le tableau suivant créé:MySQL InnoDB question de blocage

mysql>CREATE TABLE IF NOT EXISTS `SeqNum` 
    (
    `id` varchar(10) NOT NULL, 
    `seq_num` BIGINT(30) default 0, 
     PRIMARY KEY(`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
    Query OK, 0 rows affected (0.00 sec) 

    mysql>INSERT IGNORE INTO `SeqNum` VALUES('current',0); 
    Query OK, 1 rows affected (0.00 sec) 

Maintenant, j'ai deux connexions MySQL à la même base de données, je les nommer en tant que fils A et B. Dans le thread A, je l'instruction SQL suivante:

mysql> begin; 
    Query OK, 0 rows affected (0.00 sec) 

    mysql> select `seq_num` from SeqNum where `id`='current' FOR UPDATE; 
     +---------+ 
     | seq_num | 
     +---------+ 
     |  0 | 
     +---------+ 
     1 row in set (0.01 sec) 

puis, je laisse le thread A tel quel.

En fil B, je voudrais faire la même requête:

mysql> begin; 
    Query OK, 0 rows affected (0.00 sec) 

    mysql>SELECT `current_seq_num` FROM SeqNum WHERE `id` = 'current' FOR UPDATE; 

fil B jetteront un MySQL 1205 erreur après le temps d'attente lock-out: délai de verrouillage d'attente dépassé; essayez de redémarrer la transaction.

Il est logique que threadA place un verrou 'X' sur cette ligne, de sorte que le thread B ne puisse pas obtenir le 'X' de verrouillage tant que le thread A n'a pas relâché le verrou. Maintenant, ma question est: du point de vue du thread B, comment pourrais-je savoir quel thread/connexion bloque ma requête (pour obtenir le privilège 'UPDATE' pour la table 'SeqNum') quand MySQL me renvoie l'erreur 1205 ? Si threadA ne fait rien après avoir obtenu le verrou X, et que j'exécute 'show processlist' dans le thread B, tout ce que j'ai sont: plusieurs threads avec le statut 'Sleep' (je suppose qu'il y a plus de deux threads connectés à la base) , Je ne peux pas identifier quel fil a bloqué ma demande?

J'espère que j'ai clairement expliqué la question. Merci!

Répondre

0

Êtes-vous dans une transaction sur les deux sessions, à savoir que vous avez saisi

START TRANSACTION 

Normalement, le comportement serait que vous le désirez, à savoir un FOR UPDATE serait tout simplement bloquer jusqu'à ce que la serrure était disponible (en raison de COMMIT ou ROLLBACK à partir de la première transaction)

+0

Oui, les deux sessions sont dans une transaction. Je viens d'ajouter la déclaration de transaction dans ma question. Ma question n'est pas de savoir pourquoi la 1ère session a bloqué la 2ème session. Mais, du point de vue de la 2ème session, comment savoir quelle session a bloqué sa requête? Bien sûr, je suppose qu'il y a plus de deux sessions. – WilliamLou

+0

et j'ai mal lu votre question, je pensais que vous obteniez le délai d'attente immédiatement, je suis désolé! –

4

Vous pouvez facilement savoir si vous utilisez une version plus récente (InnoDB Plugin). Il y a des tables dans le schéma d'information que vous pouvez interroger:

  • SELECT * FROM information_schema.innodb_trx;
  • SELECT * FROM information_schema.innodb_locks;

Dans le tableau innodb_trx il devrait y avoir une colonne appelée 'trx_mysql_thread_id' (ou similaire - il est trx_mysql_thread_id dans MySQL 5.5). C'est l'identifiant dans SHOW PROCESSLIST.

(Notez que innodb_locks est mal nommé, il ne sera renseigné que pour les verrous, pas pour les verrous).

7

plug-in InnoDB vous donnera une image claire de la verrouillé et les requêtes de verrouillage.

Par exemple

SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, 
     r.trx_query waiting_query, 
     b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread, 
     b.trx_query blocking_query 
FROM  information_schema.innodb_lock_waits w 
INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id 
INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id; 

vous donnera un verrouillage et des opérations de blocage. Seulement, vous devez avoir installé le plugin innodb.