J'exécute la commande ALTER
suivante sur une base de données MySQL 5.6 sur une grande table avec 60 millions de lignes:
ALTER TABLE `large_table` ADD COLUMN `note` longtext NULL,
ALGORITHM=INPLACE, LOCK=NONE;
Malgré la spécification des deux ALGORITHM=INPLACE
et LOCK=NONE
, la table est verrouillée et supprime essentiellement l'application jusqu'à la fin de la migration.
J'ai vérifié que la table était bien verrouillée en vérifiant la valeur de In_use
colonne sur la sortie du SHOW OPEN TABLES
commande. Il a été défini sur 1
.
D'après ce que j'ai rassemblé dans la documentation MySQL, cette opération ne devrait pas verrouiller la table. Et, MySQL est censé faire échouer la commande s'il ne peut pas continuer sans verrou. J'ai mis à niveau la base de données vers MySQL 5.7 pour voir si elle est meilleure, mais je rencontre également le même problème sur 5.7.
Est-ce un comportement attendu? Comment savoir ce qui ne va pas ici?
Je suppose que vous ne faisiez pas d'autre DDL sur cette table à peu près en même temps?
Pour le futur:
8.0.12 a ALTER TABLE .. ALGORITHM=INSTANT
Pour ADD COLUMN
. Voir Discussion et ALTER Reference et Référence DDL en ligne
Les limitations suivantes s'appliquent lorsque l'algorithme INSTANT est utilisé pour ajouter une colonne:
Plusieurs colonnes peuvent être ajoutées dans la même instruction ALTER TABLE.
Si vous ne pouvez pas mettre à niveau, envisagez le pt-online-schema-change
De Percona ou un nouveau produit concurrent gh-ost
(Qui utilise le binlog).
J'ai également rencontré des problèmes avec le verrouillage de MySQL 5.6 même lorsque ALGORITHM=INPLACE, LOCK=NONE;
est utilisé. Je voudrais d'abord vérifier les points suivants:
Vérifier les contraintes sur la table
La clause ALTER TABLE LOCK = NONE n'est pas autorisée s'il existe des contraintes ON ... CASCADE ou ON ... SET NULL sur la table.
Source: https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-limitations.html
La table a-t-elle une relation de clé étrangère?
Une opération DDL en ligne sur une table dans une relation de clé étrangère n'attend pas qu'une transaction s'exécutant sur l'autre table de la relation de clé étrangère soit validée ou annulée. La transaction contient un verrou de métadonnées exclusif sur la table qu'elle met à jour et un verrou de métadonnées partagé sur la table liée à la clé étrangère (requis pour la vérification de la clé étrangère). Le verrou de métadonnées partagé permet à l'opération DDL en ligne de se poursuivre mais bloque l'opération dans sa phase finale, lorsqu'un verrou de métadonnées exclusif est requis pour mettre à jour la définition de la table. Ce scénario peut entraîner des blocages lorsque d'autres transactions attendent la fin de l'opération DDL en ligne.
Source: https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-limitations.html
Et lisez le verrouillage des métadonnées ici: https://dev.mysql.com/doc/refman/5.6/en/metadata-locking.html
Modifier d'abord les tables de l'ancien format de temps
Si vous avez créé vos tables avant MySQL 5.6 avec des champs DATETIME ou TIMESTAMP, elles doivent être mises à niveau vers le nouveau format 5.6 de MySQL.
Les tables InnoDB créées avant MySQL 5.6 ne prennent pas en charge ALTER TABLE ... ALGORITHM = INPLACE pour les tables qui incluent des colonnes temporelles (DATE, DATETIME ou TIMESTAMP) et n'ont pas été reconstruites à l'aide de ALTER TABLE ... ALGORITHM = COPY. Dans ce cas, une opération ALTER TABLE ... ALGORITHM = INPLACE renvoie l'erreur suivante:
ERREUR 1846 (0A000): ALGORITHM = INPLACE n'est pas pris en charge. Motif: impossible de modifier le type de colonne INPLACE. Essayez ALGORITHM = COPY.
Source: https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-limitations.html
Vérifiez si la table a un partitionnement
Le partitionnement modifie la façon dont les règles de table s'appliquent. Vérifier l'état de partitionnement de la table
show table status;
Recherchez "Moteur" ne correspondant pas à InnoDB
Sources: https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.html#online-ddl-partitioning
Enfin, comme Rick James l'a mentionné dans sa réponse, la mise à niveau de 5.6 à 8.0 peut être une option car elle fournit d'autres améliorations.