web-dev-qa-db-fra.com

MySQL 5.6 - table se verrouille même lorsque ALGORITHM = inplace est utilisé

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?

10
jeffreyveon

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:

  • L'ajout d'une colonne ne peut pas être combiné dans la même instruction avec d'autres actions ALTER TABLE qui ne prennent pas en charge ALGORITHM = INSTANT.
  • Une colonne ne peut être ajoutée que comme dernière colonne du tableau. L'ajout d'une colonne à toute autre position parmi d'autres colonnes n'est pas pris en charge.
  • Les colonnes ne peuvent pas être ajoutées aux tables qui utilisent ROW_FORMAT = COMPRESSED.
  • Les colonnes ne peuvent pas être ajoutées aux tables qui incluent un index FULLTEXT.
  • Les colonnes ne peuvent pas être ajoutées aux tables temporaires. Les tables temporaires ne prennent en charge que ALGORITHM = COPY.
  • Les colonnes ne peuvent pas être ajoutées aux tables qui résident dans l'espace de table du dictionnaire de données.
  • Les limites de taille de ligne ne sont pas évaluées lors de l'ajout d'une colonne. Cependant, les limites de taille de ligne sont vérifiées lors des opérations DML qui insèrent et mettent à jour des lignes dans le tableau.

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).

4
Rick James

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.

2
Chris