Les blocages InnoDB sont-ils exclusifs à INSERT / UPDATE / DELETE?

8

Je travaille autour de l'erreur MySQL "Deadlock trouvé lors de la tentative de verrouillage; essayez de redémarrer la transaction" .

Je vais devoir mettre à jour un programme pour autoriser les blocages. Est-il possible que cette SELECTinstruction produise des erreurs de blocage? Je sais que ce n'est qu'un verrou en lecture, donc les sélections multiples ne seront pas un problème, mais qu'en est-il s'il y a une instruction INSERT, UPDATEou (avec des sous-requêtes possibles avec des jointures) et une instruction (possible avec des jointures ou des sous-requêtes) ?DELETESELECT

Est-il possible que l'erreur soit lancée à la SELECTplace de INSERT, UPDATEou DELETE.

L'histoire est ici si vous êtes curieux.

Bryan Field
la source
+1 pour cela est une bonne question car cela met en évidence une bizarrerie InnoDB dont la plupart des gens ne sont pas conscients en conjonction avec SELECT sur les tables InnoDB.
RolandoMySQLDBA,

Réponses:

5

La réponse directe au titre de votre question est Non.

Les requêtes SELECT peuvent effectuer des verrous sur gen_clust_index , alias l'index clusterisé.

Voici trois questions sur les échanges de piles DBA que j'ai examinées avec agressivité avec @RedBlueThing , la personne qui a posé ces questions. @RedBlueThing a trouvé des solutions à ses questions.

Juste pour garder votre question en perspective, lorsque vous regardez ces réponses (ne regardez pas trop profondément, même si j'ai le vertige en regardant mes propres réponses alambiquées), il devrait être rapidement évident que les requêtes SELECT peuvent verrouiller les données.

Vous avez également des cas spéciaux de SELECT où vous pouvez verrouiller des lignes spécifiques à la demande .

MISE À JOUR 2011-08-08 16:49 EDT

Vous avez posé la question de variation: "Les exceptions de blocage InnoDB vont-elles être levées par SELECT"? La réponse à cette question peut être Oui sous certaines conditions. Quelle est cette condition? Si une seule instruction SQL est annulée à la suite d'une erreur, certains des verrous définis par l'instruction peuvent être conservés. Cela se produit car InnoDB stocke les verrous de ligne dans un format tel qu'il ne peut pas savoir par la suite quel verrou a été défini par quelle instruction .

Sur la base de cette déclaration, les séquences d'événements à l'origine de cela pourraient théoriquement être les suivantes:

  • Votre SQL UPDATEs une seule ligne mais génère une erreur
  • La MISE À JOUR provoque une restauration de la première ligne
  • La rangée a une serrure persistante

Personnellement, cette dernière déclaration me fait peur. Il aurait été bien que MySQL informe tout le monde de cette bizarrerie. Pourtant, cette déclaration provient de la documentation MySQL. (Oh oui, Oracle possède InnoDB)

MISE À JOUR 2015-09-22 18:40 EST

Plus tôt dans l'année, j'ai appris que Percona avait un bon chèque Nagios pour trouver ces serrures embêtantes cachées derrière des connexions endormies. Il ne vous reste plus qu'à exécuter le code à partir de ce lien:

SELECT COALESCE(MAX(IF(p.command = 'Sleep', p.time, 0)), 0) AS idle_in_trx
FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS AS w
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX        AS b ON  b.trx_id = w.blocking_trx_id
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX        AS r ON  r.trx_id = w.requesting_trx_id
LEFT JOIN  INFORMATION_SCHEMA.PROCESSLIST       AS p ON  p.id     = b.trx_mysql_thread_id;

Cela ne fonctionnera que pour MySQL 5.5+. Si vous avez MySQL 5.1 ou une version antérieure, vous devez tuer toutes les connexions en veille pour libérer les verrous.

RolandoMySQLDBA
la source
@Rolando - n'est-ce pas vrai avec le MVCC d'InnoDB qui lit jamais bloquer (sauf lorsque vous utilisez for updatebien sûr)?
Jack dit d'essayer topanswers.xyz
@Jack - Si vous lisez les liens dans les 3 premières puces, vous verrez que MVCC n'est pas en cause. C'est une impasse profonde dans l'index clusterisé que même MVCC ne peut pas atténuer.
RolandoMySQLDBA
@Rolando - J'ai lu les liens un peu plus attentivement et je ne vois toujours aucune indication qu'un normal selectpeut verrouiller des lignes ou être bloqué par DML dans une autre transaction. C'est certainement vrai pour Oracle et pour autant que je sache, c'est aussi vrai pour InnoDB? Sauf le cas où l' selectinstruction fait réellement du DML via une fonction ou une autre route circulaire bien sûr.
Jack dit d'essayer topanswers.xyz
@Jack - Si les SELECT peuvent bloquer un index, combien plus une UPDATE comme le montrent mes 3 premiers liens.
RolandoMySQLDBA