2010-05-13 5 views
2

La documentation typique sur le verrouillage de l'innodb est trop confuse. Je pense que ce sera d'une grande valeur pour avoir un « mannequins guident InnoDB verrouillage »Guide pratique pour le verrouillage de l'innodb

Je vais commencer, et je rassemblerai toutes les réponses comme un wiki:

  • La colonne doit être indexé avant la ligne le verrouillage de niveau s'applique.
    • EXEMPLE: ligne de suppression où colonne1 = 10; verrouille la table à moins colonne1 est indexé

Répondre

2

Voici mes notes de travailler avec le support de MySQL sur un problème de verrouillage récent, étrange (version 5.1.37):

Toutes les lignes et les entrées d'index traversé pour obtenir les lignes en cours de modification sera verrouillé. Il est couvert à:

http://dev.mysql.com/doc/refman/5.1/en/innodb-locks-set.html

« Une lecture de verrouillage, une instruction UPDATE, ou une suppression des verrous d'enregistrement généralement fixés sur chaque enregistrement d'index qui est numérisé dans le traitement de l'instruction SQL Peu importe s'il existe. Conditions WHERE dans l'instruction qui exclut la ligne InnoDB ne se souvient pas de la condition WHERE exacte, mais ne sait que les plages d'index ont été analysées ... Si vous n'avez aucun index approprié pour votre déclaration et MySQL doit analyser la table entière pour traiter l'instruction, chaque ligne de la table devient verrouillée, ce qui bloque à son tour tous les inserts des autres utilisateurs sur la table. "

C'est un mal de tête MAJEUR si c'est vrai.

C'est. Une solution de contournement qui est souvent utile est de faire:

MISE À JOUR quelquechose définissable quelquechose à quelquechose où primarykey dans (sélectionnez la clé primaire à partir de quelquechose où les contraintes sont classées par la clé primaire); La sélection interne n'a pas besoin de verrous et la mise à jour aura alors moins de travail à faire pour la mise à jour. La clause order by garantit que la mise à jour est effectuée dans l'ordre des clés primaires pour correspondre à l'ordre physique d'InnoDB, le moyen le plus rapide de le faire.

Lorsque de grands nombres de lignes sont impliqués, comme dans votre cas, il peut être préférable de stocker le résultat de sélection dans une table temporaire avec une colonne de drapeau ajoutée. Sélectionnez ensuite dans la table temporaire où l'indicateur n'est pas défini pour obtenir chaque lot. Exécutez les mises à jour avec une limite de dis 1000 ou 10000 et définissez l'indicateur pour le lot après la mise à jour. Les limites maintiendront la quantité de verrouillage à un niveau tolérable tandis que le travail sélectionné devra seulement être fait une fois. Validez après chaque lot pour libérer les verrous.

Vous pouvez également accélérer ce travail en effectuant une somme de sélection d'une colonne non indexée avant d'effectuer chaque lot de mises à jour. Cela chargera les pages de données dans le pool de mémoire tampon sans prendre de verrous. Ensuite, le verrouillage durera moins longtemps car il n'y aura aucune lecture de disque.

Ce n'est pas toujours pratique mais quand c'est le cas, cela peut être très utile. Si vous ne pouvez pas le faire par lots, vous pouvez au moins essayer le premier pour précharger les données, s'il est suffisamment petit pour tenir dans le pool de mémoire tampon.

Si possible, utilisez le mode d'isolation de transaction READ COMMITTED.Voir:

http://dev.mysql.com/doc/refman/5.1/en/set-transaction.html

Pour obtenir ce verrouillage nécessite l'utilisation réduite de l'exploitation forestière binaire basée sur les lignes (plutôt que l'enregistrement binaire basé sur une instruction par défaut).

Deux problèmes connus:

  1. Subqueries peut être inférieur idéalement optimisé parfois. Dans ce cas, il s'agissait d'une sous-requête dépendante indésirable - la suggestion que j'ai faite d'utiliser une sous-requête s'est avérée inutile par rapport à l'alternative dans ce cas à cause de cela.

  2. Les suppressions et les mises à jour n'ont pas la même gamme de plans de requête que les instructions select, il est parfois difficile de les optimiser correctement sans mesurer les résultats pour déterminer exactement ce qu'ils font.

Ces deux éléments s'améliorent progressivement. Ce bug est un exemple où nous avons juste amélioré les optimisations disponibles pour une mise à jour, même si les changements sont importants et il va encore à travers QA pour être sûr qu'il n'a pas de grands effets indésirables:

http://bugs.mysql.com/bug.php?id=36569

Questions connexes