Lorsque vous exécutez une instruction ALTER TABLE dans MySQL, la table entière est verrouillée en lecture (autorisant les lectures simultanées, mais interdisant les écritures simultanées) pendant la durée de l'instruction. S'il s'agit d'une grande table, les instructions INSERT ou UPDATE peuvent être bloquées pendant un temps looooong. Existe-t-il un moyen de faire une "modification à chaud", comme l'ajout d'une colonne de telle sorte que la table puisse toujours être mise à jour tout au long du processus?
La plupart du temps, je suis intéressé par une solution pour MySQL, mais je serais intéressé par d'autres SGBDR si MySQL ne peut pas le faire.
Pour clarifier, mon objectif est simplement d'éviter les temps d'arrêt lorsqu'une nouvelle fonctionnalité nécessitant une colonne de table supplémentaire est mise en production. Tout schéma de base de données va changer au fil du temps, qui est juste un fait de la vie. Je ne vois pas pourquoi nous devrions accepter que ces changements entraînent inévitablement des temps d'arrêt; c'est juste faible.
la source
Réponses:
La seule autre option est de faire manuellement ce que de nombreux systèmes SGBDR font de toute façon ...
- Créer une nouvelle table
Vous pouvez ensuite copier le contenu de l'ancienne table sur un morceau à la fois. Tout en étant toujours prudent de tout INSERT / UPDATE / DELETE sur la table source. (Peut être géré par un déclencheur. Bien que cela entraînerait un ralentissement, ce n'est pas un verrou ...)
Une fois terminé, changez le nom de la table source, puis changez le nom de la nouvelle table. De préférence dans une transaction.
Une fois terminé, recompilez toutes les procédures stockées, etc. qui utilisent cette table. Les plans d'exécution ne seront probablement plus valides.
ÉDITER:
Certains commentaires ont été faits sur le fait que cette limitation est un peu faible. Alors j'ai pensé mettre une nouvelle perspective dessus pour montrer pourquoi c'est comme ça ...
la source
Percona crée un outil appelé pt-online-schema-change qui permet de le faire.
Il fait essentiellement une copie de la table et modifie la nouvelle table. Pour garder la nouvelle table synchronisée avec l'original, il utilise des déclencheurs pour se mettre à jour. Cela permet d'accéder à la table d'origine pendant que la nouvelle table est préparée en arrière-plan.
Ceci est similaire à la méthode suggérée par Dems ci-dessus, mais cela se fait de manière automatisée.
Certains de leurs outils ont une courbe d'apprentissage, à savoir la connexion à la base de données, mais une fois que vous l'avez, ce sont d'excellents outils à avoir.
Ex:
la source
Cette question de 2009. Maintenant, MySQL propose une solution:
DDL en ligne (langage de définition de données)
Il vous permet d'ajuster l'équilibre entre les performances et la concurrence pendant l'opération DDL, en choisissant de bloquer entièrement l'accès à la table (clause LOCK = EXCLUSIVE), d'autoriser les requêtes mais pas de DML (clause LOCK = SHARED), ou d'autoriser les requêtes complètes et DML accès à la table (clause LOCK = NONE). Lorsque vous omettez la clause LOCK ou spécifiez LOCK = DEFAULT, MySQL autorise autant de concurrence que possible en fonction du type d'opération.
Si possible, effectuer des modifications sur place, plutôt que de créer une nouvelle copie de la table, évite les augmentations temporaires de l'utilisation de l'espace disque et de la surcharge d'E / S associées à la copie de la table et à la reconstruction des index secondaires.
voir MySQL 5.6 Reference Manual -> InnoDB and Online DDL pour plus d'informations.
Il semble que DDL en ligne soit également disponible dans MariaDB
MariaDB KB sur ALTER TABLE
la source
Voir l'outil de changement de schéma en ligne de Facebook.
http://www.facebook.com/notes/mysql-at-facebook/online-schema-change-for-mysql/430801045932
Pas pour les faibles de cœur; mais cela fera l'affaire.
la source
Je recommande Postgres si c'est une option. Avec postgres, il n'y a pratiquement pas de temps d'arrêt avec les procédures suivantes:
Une autre fonctionnalité intéressante est que la plupart des instructions DDL sont transactionnelles, vous pouvez donc effectuer une migration entière dans une transaction SQL, et si quelque chose ne va pas, tout est annulé.
Je l'ai écrit il y a un peu, cela peut peut-être nous éclairer davantage sur les autres mérites.
la source
Puisque vous avez posé des questions sur d'autres bases de données, voici quelques informations sur Oracle.
L'ajout d'une colonne NULL à une table Oracle est une opération très rapide car elle ne met à jour que le dictionnaire de données. Cela maintient un verrou exclusif sur la table pendant une très courte période de temps. Cependant, cela invalidera toutes les procédures stockées, vues, déclencheurs, etc. qui seront automatiquement recompilés.
De là, si nécessaire, vous pouvez créer un index à l'aide de la clause ONLINE. Encore une fois, seuls les verrous de dictionnaire de données très courts. Il lira le tableau entier à la recherche de choses à indexer, mais ne bloquera personne en faisant cela.
Si vous devez ajouter une clé étrangère, vous pouvez le faire et demander à Oracle de vous assurer que les données sont correctes. Sinon, il doit lire toute la table et valider toutes les valeurs qui peuvent être lentes (créez d'abord votre index).
Si vous avez besoin de mettre une valeur par défaut ou calculée dans chaque ligne de la nouvelle colonne, vous devrez exécuter une mise à jour massive ou peut-être un petit programme utilitaire qui remplit les nouvelles données. Cela peut être lent, surtout si les rangées deviennent beaucoup plus grandes et ne rentrent plus dans leurs blocs. Le verrouillage peut être géré pendant ce processus. Étant donné que l'ancienne version de votre application, qui est toujours en cours d'exécution, ne connaît pas cette colonne, vous pourriez avoir besoin d'un déclencheur sournois ou de spécifier une valeur par défaut.
À partir de là, vous pouvez faire un switcharoo sur vos serveurs d'applications vers la nouvelle version du code et il continuera à fonctionner. Lâchez votre gâchette sournoise.
Alternativement, vous pouvez utiliser DBMS_REDEFINITION qui est une boîte noire conçue pour faire ce genre de chose.
Tout cela est tellement embêtant à tester, etc. que nous avons juste une panne tôt le dimanche matin chaque fois que nous sortons une version majeure.
la source
Si vous ne pouvez pas vous permettre de temps d'arrêt pour votre base de données lors de la mise à jour des applications, vous devez envisager de maintenir un cluster à deux nœuds pour une haute disponibilité. Avec une configuration de réplication simple, vous pouvez effectuer des changements structurels presque entièrement en ligne comme celui que vous suggérez:
Ce n'est pas toujours facile mais ça marche, généralement avec 0 temps d'arrêt! Le deuxième nœud ne doit pas être uniquement passif, il peut être utilisé pour tester, faire des statistiques ou comme nœud de secours. Si vous n'avez pas d'infrastructure, la réplication peut être configurée sur une seule machine (avec deux instances de MySQL).
la source
Nan. Si vous utilisez des tables MyISAM, à ma meilleure compréhension, ils ne font que des verrous de table - il n'y a pas de verrous d'enregistrement, ils essaient simplement de tout garder ultra-rapide grâce à la simplicité. (D'autres tables MySQL fonctionnent différemment.) Dans tous les cas, vous pouvez copier la table dans une autre table, la modifier, puis les changer, en mettant à jour les différences.
Il s'agit d'une modification si massive que je doute qu'un SGBD le supporte. C'est considéré comme un avantage de pouvoir le faire avec les données du tableau en premier lieu.
la source
Solution temporaire...
Une autre solution pourrait être d'ajouter une autre table avec la clé primaire de la table d'origine, ainsi que votre nouvelle colonne.
Remplissez votre clé primaire sur la nouvelle table et remplissez les valeurs de la nouvelle colonne dans votre nouvelle table, et modifiez votre requête pour joindre cette table pour les opérations de sélection et vous devez également insérer, mettre à jour séparément pour cette valeur de colonne.
Lorsque vous parvenez à obtenir des temps d'arrêt, vous pouvez modifier la table d'origine, modifier vos requêtes DML et supprimer votre nouvelle table créée précédemment
Sinon, vous pouvez opter pour la méthode de clustering, la réplication, l'outil pt-online-schema de percona
la source
En utilisant le plugin Innodb, les instructions ALTER TABLE qui ajoutent ou suppriment uniquement des index secondaires peuvent être faites "rapidement", c'est-à-dire sans reconstruire la table.
De manière générale cependant, dans MySQL, toute ALTER TABLE implique la reconstruction de la table entière, ce qui peut prendre un temps très long (c'est-à-dire si la table contient une quantité utile de données).
Vous devez vraiment concevoir votre application de manière à ce que les instructions ALTER TABLE n'aient pas à être effectuées régulièrement; vous ne voulez certainement pas qu'ALTER TABLE soit exécuté pendant l'exécution normale de l'application, sauf si vous êtes prêt à attendre ou que vous modifiez de minuscules tables.
la source
Je recommanderais l'une des deux approches:
Concevez vos tables de base de données en gardant à l'esprit les changements potentiels. Par exemple, j'ai travaillé avec des systèmes de gestion de contenu, qui modifient régulièrement les champs de données dans le contenu. Au lieu de créer la structure de la base de données physique pour répondre aux exigences initiales du champ CMS, il est préférable de créer une structure flexible. Dans ce cas, utilisez un champ de texte blob (varchar (max) par exemple) pour contenir des données XML flexibles. Cela rend les changements structurels très moins fréquents. Les changements structurels peuvent être coûteux, il y a donc un avantage à coûter ici aussi.
Avoir le temps de maintenance du système. Soit le système se met hors ligne pendant les modifications (mensuelles, etc.), et les modifications sont planifiées à l'heure la moins fréquentée de la journée (3 à 5 heures du matin, par exemple). Les changements sont mis en place avant le déploiement de la production, vous aurez donc une bonne estimation de la fenêtre fixe des temps d'arrêt.
2a. Avoir des serveurs redondants, de sorte que lorsque le système a des temps d'arrêt, l'ensemble du site ne tombe pas en panne. Cela vous permettrait de "déployer" vos mises à jour de manière échelonnée, sans interrompre tout le site.
Les options 2 et 2a peuvent ne pas être réalisables; ils ont tendance à ne concerner que les sites / opérations plus importants. Ce sont des options valides, cependant, et j'ai personnellement utilisé toutes les options présentées ici.
la source
Si quelqu'un est encore en train de lire ceci ou arrive à venir ici, c'est le gros avantage de l'utilisation d'un système de base de données NoSQL comme mongodb. J'ai eu le même problème avec la modification de la table pour ajouter des colonnes pour des fonctionnalités supplémentaires ou des index sur une grande table avec des millions de lignes et des écritures élevées. Cela finirait par se bloquer pendant très longtemps, donc faire cela sur la base de données LIVE frustrerait nos utilisateurs. Sur de petites tables, vous pouvez vous en sortir.
Je déteste le fait que nous devions «concevoir nos tableaux pour éviter de les altérer». Je ne pense tout simplement pas que cela fonctionne dans le monde des sites Web d'aujourd'hui. Vous ne pouvez pas prédire comment les gens utiliseront votre logiciel, c'est pourquoi vous changez rapidement les choses en fonction des commentaires des utilisateurs. Avec mongodb, vous pouvez ajouter des "colonnes" à volonté sans temps d'arrêt. Vous ne les ajoutez même pas vraiment, vous insérez simplement des données avec de nouvelles colonnes et il le fait automatiquement.
Vaut le détour: www.mongodb.com
la source
En général, la réponse sera «non». Vous modifiez la structure de la table, ce qui nécessitera potentiellement de nombreuses mises à jour "et je suis tout à fait d'accord avec cela. Si vous prévoyez de le faire souvent, je proposerai une alternative aux colonnes" factices "- utilisez
VIEW
plutôt s de tables pourSELECT
les données. IIRC, la modification de la définition d'une vue est relativement légère et l'indirection à travers une vue est effectuée lorsque le plan de requête est compilé. La dépense est que vous auriez à ajouter la colonne à une nouvelle table et faire le vueJOIN
dans la colonne.Bien sûr, cela ne fonctionne que si vous pouvez utiliser des clés étrangères pour effectuer une cascade de suppressions et autres. L'autre avantage est que vous pouvez créer une nouvelle table contenant une combinaison des données et y pointer la vue sans perturber l'utilisation du client.
Juste une pensée.
la source
La différence entre Postgres et MySQL à cet égard est que dans Postgres, il ne recrée pas une table, mais modifie le dictionnaire de données qui est similaire à Oracle. Par conséquent, l'opération est rapide, alors qu'elle nécessite toujours d'allouer un verrou de table DDL exclusif pendant très peu de temps, comme indiqué ci-dessus par d'autres.
Dans MySQL, l'opération copiera les données dans une nouvelle table tout en bloquant les transactions, ce qui était le principal problème pour les DBA MySQL avant la version 5.6.
La bonne nouvelle est que depuis la sortie de MySQL 5.6, la restriction a été en grande partie levée et vous pouvez maintenant profiter de la véritable puissance de la base de données MYSQL.
la source
Comme SeanDowney l'a mentionné,
pt-online-schema-change
c'est l'un des meilleurs outils pour faire ce que vous avez décrit dans la question ici. J'ai récemment fait beaucoup de changements de schéma sur une base de données en direct et cela s'est plutôt bien passé. Vous pouvez en savoir plus sur mon article de blog ici: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/ .la source
Vous devriez certainement essayer
pt-online-schema-change
. J'utilise cet outil pour effectuer des migrations sur AWS RDS avec plusieurs esclaves et cela a très bien fonctionné pour moi. J'ai écrit un article de blog élaboré sur la façon de faire ce qui pourrait vous être utile.Blog: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/
la source
Les colonnes factices sont une bonne idée si vous pouvez prédire leur type (et les rendre nulles). Vérifiez comment votre moteur de stockage gère les valeurs nulles.
MyISAM verrouille tout si vous mentionnez même un nom de table au passage, au téléphone, à l'aéroport. Il fait juste ça ...
Cela étant dit, les serrures ne sont pas vraiment un problème; tant que vous n'essayez pas d'ajouter une valeur par défaut pour la nouvelle colonne à chaque ligne, mais laissez-la reposer comme nulle, et que votre moteur de stockage est suffisamment intelligent pour ne pas l'écrire, vous devriez accepter un verrou qui n'est que tenu suffisamment longtemps pour mettre à jour les métadonnées. Si vous essayez d'écrire une nouvelle valeur, eh bien, vous portez un toast.
la source
TokuDB peut ajouter / supprimer des colonnes et ajouter des index "à chaud", la table est entièrement disponible tout au long du processus. Il est disponible via www.tokutek.com
la source
Pas vraiment.
Vous modifiez la structure sous-jacente de la table, après tout, et c'est un peu d'information qui est assez importante pour le système sous-jacent. Vous déplacez également (probablement) une grande partie des données sur le disque.
Si vous prévoyez de faire beaucoup cela, il vaut mieux simplement remplir le tableau avec des colonnes «factices» qui sont disponibles pour une utilisation future.
la source