J'ai besoin de créer un index sur une table MySQL d'environ 5 millions de lignes. C'est une table de production et je crains un blocage complet de tout si je lance une instruction CREATE INDEX ...
Existe-t-il un moyen de créer cet index sans bloquer les insertions et les sélections?
Je me demande juste de ne pas m'arrêter, créer un index et redémarrer mon système!
https://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html
Dans MySQL 5.6 et les versions ultérieures, la table reste disponible pour les opérations de lecture et d'écriture pendant la création ou la suppression de l'index. L'instruction CREATE INDEX ou DROP INDEX ne se termine qu'une fois que toutes les transactions qui accèdent à la table sont terminées, de sorte que l'état initial de l'index reflète le contenu le plus récent de la table. Auparavant, la modification de la table lors de la création ou de la suppression d'un index entraînait généralement un blocage qui annulait l'instruction INSERT, UPDATE ou DELETE de la table.
De la réponse ci-dessus:
"Si vous utilisez une version supérieure à 5.1, des index sont créés alors que la base de données est en ligne. Ne vous inquiétez donc pas, vous n'interromprez pas l'utilisation du système de production."
C'est faux**** (du moins pour les tables MyISAM/InnoDB, utilisées par 99,999% des utilisateurs. L’édition en cluster est différente.)
Effectuer des opérations UPDATE sur une table va [~ # ~] bloquer [~ # ~] pendant la création de l'index. MySQL est vraiment, vraiment stupide à ce sujet (et quelques autres choses).
Script de test:
(
for n in {1..50}; do
#(time mysql -uroot -e 'select * from website_development.users where id = 41225\G'>/dev/null) 2>&1 | grep real;
(time mysql -uroot -e 'update website_development.users set bio="" where id = 41225\G'>/dev/null) 2>&1 | grep real;
done
) | cat -n &
PID=$!
sleep 0.05
echo "Index Update - START"
mysql -uroot website_development -e 'alter table users add index ddopsonfu (last_name, email, first_name, confirmation_token, current_sign_in_ip);'
echo "Index Update - FINISH"
sleep 0.05
kill $PID
time mysql -uroot website_development -e 'drop index ddopsonfu on users;'
Mon serveur (InnoDB):
Server version: 5.5.25a Source distribution
Sortie (remarquez comment la 6ème opération bloque pendant environ 400 ms pour terminer la mise à jour de l'index):
1 real 0m0.009s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.012s
5 real 0m0.009s
Index Update - START
Index Update - FINISH
6 real 0m0.388s
7 real 0m0.009s
8 real 0m0.009s
9 real 0m0.009s
10 real 0m0.009s
11 real 0m0.009s
Vs lire les opérations qui ne bloquent pas (permutez le commentaire de ligne dans le script):
1 real 0m0.010s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.010s
5 real 0m0.009s
Index Update - START
6 real 0m0.010s
7 real 0m0.010s
8 real 0m0.011s
9 real 0m0.010s
...
41 real 0m0.009s
42 real 0m0.010s
43 real 0m0.009s
Index Update - FINISH
44 real 0m0.012s
45 real 0m0.009s
46 real 0m0.009s
47 real 0m0.010s
48 real 0m0.009s
Ainsi, il n'y a qu'une seule méthode que je connaisse pour mettre à jour un schéma MySql et ne pas subir de panne de disponibilité. Maîtres circulaires:
Un moyen simple de mettre à jour le schéma n'est pas le cas. Réalisable dans un environnement de production sérieux; Oui, ça l'est. S'il vous plaît, s'il vous plaît, s'il y a un moyen plus facile d'ajouter un index à une table MySQL sans bloquer les écritures, faites le moi savoir.
Googler m'a conduit à cet article qui décrit une technique similaire. Mieux encore, ils conseillent de boire au même moment de la procédure (notez que j'ai écrit ma réponse avant de lire l'article)!
Le article J'ai lié ci-dessus parle d'un outil, pt-online-schema-change , qui fonctionne comme suit:
Je n'ai jamais essayé l'outil moi-même. YMMV
J'utilise actuellement MySQL via le RDS d'Amazon . C'est un service vraiment astucieux qui encapsule et gère MySQL, vous permettant d'ajouter de nouveaux réplicas en lecture avec un seul bouton et de mettre à niveau de manière transparente la base de données sur des SKU de matériel. C'est vraiment pratique. Vous n’obtenez pas un SUPER accès à la base de données, vous ne pouvez donc pas visser directement avec la réplication (est-ce une bénédiction ou une malédiction?). Cependant, vous pouvez utiliser Promotion sur les répliques en lecture pour apporter les modifications de schéma sur un esclave en lecture seule, puis promouvoir cet esclave pour qu'il devienne votre nouveau maître. Exactement le même truc que je viens de décrire, mais beaucoup plus facile à exécuter. Ils ne font toujours pas grand chose pour vous aider avec le cut-over. Vous devez reconfigurer et redémarrer votre application.
Comme cela article de blog , le mécanisme InnoDB ALTER TABLE
A été complètement repensé pour MySQL 5.6.
(Pour un aperçu exclusif de ce sujet, le documentation MySQL peut fournir une lecture d'un après-midi.)
Pour ajouter un index à une table sans verrou résultant sur UPDATE
/INSERT
, le format d'instruction suivant peut être utilisé:
ALTER TABLE my_table ADD INDEX my_table__idx (my_column), ALGORITHM=INPLACE, LOCK=NONE;
Mise à jour MySQL 5.6 (février 2013): Vous pouvez désormais effectuer des opérations de lecture et d'écriture pendant la création d'un index, même avec les tables InnoDB - http://dev.mysql.com/doc/refman/5.6/en/innodb -create-index-overview.html
Dans MySQL 5.6 et les versions ultérieures, la table reste disponible pour les opérations de lecture et d'écriture pendant la création ou la suppression de l'index. L'instruction CREATE INDEX ou DROP INDEX ne se termine qu'une fois que toutes les transactions qui accèdent à la table sont terminées, de sorte que l'état initial de l'index reflète le contenu le plus récent de la table. Auparavant, la modification de la table lors de la création ou de la suppression d'un index entraînait généralement un blocage qui annulait l'instruction INSERT, UPDATE ou DELETE de la table.
et:
Dans MySQL 5.6, cette fonctionnalité devient plus générale: vous pouvez lire et écrire dans les tables pendant la création d’un index, et de nombreux autres types d’opérations ALTER TABLE peuvent être exécutés sans copier la table, sans bloquer les opérations DML, ou les deux. Ainsi, dans MySQL 5.6 et supérieur, nous appelons généralement cet ensemble de fonctionnalités le DDL en ligne plutôt que la création d'index rapide.
à partir de http://dev.mysql.com/doc/refman/5.6/fr/glossary.html#glos_fast_index_creation
pt-online-schema-change est la voie à suivre si vous voulez vraiment vous assurer que la migration ne fera pas tomber le site.
Comme je l'ai écrit dans le commentaire ci-dessus, j'ai plusieurs expériences avec pt-online-schema-change en production. Nous avons notre table principale de 20M + enregistrements et un maître -> 2 esclaves de réplication en lecture seule. J'ai effectué au moins une douzaine de migrations avec pt-online-schema-change, depuis l'ajout d'une nouvelle colonne, la modification du jeu de caractères, à l'ajout de plusieurs index. Nous servons aussi des tonnes de trafic pendant la période de migration et nous n’avons eu aucun problème. Bien sûr, vous devez tester tous les scripts de manière approfondie avant de l’utiliser en production.
J'ai essayé de regrouper les modifications dans 1 script afin que pt-online-schema-change ne copie qu'une seule fois les données. Et soyez très prudent avec le changement de nom de colonne car vous perdrez vos données. Cependant, l'ajout d'un index devrait bien se passer.