Forum Programmation.autre Méthode pour gérer les montées de version de structure de base de données

Posté par . Licence CC by-sa
6
28
août
2013

Bonjour les linuxiens !

Je viens vers vous pour savoir comment vous géreriez ce cas là.
Je bosse sur un projet open-source depuis un petit moment et pour le moment les montées de versions ce font à chque fois fromscratch.

A chaque nouvelle version, ses évolutions de base de données et je sais pas trop encore comment aborder le pb…

Déjà j'ai créé une table "versions" avec la version courante afin de savoir quelle version est en cours.
Ensuite, j'ai commencé à recenser les update, alter, create, delete, etc à faire pour la future installation

Bref, comment ca se passe dans les autres projets opensource ?

Merci d'avance pour vos réponses,
A+

  • # South

    Posté par . Évalué à 3.

    Bonsoir bonsoir,

    Jette éventuellement un coup d’œil du coté du logiciel South, qui est censé facilité ça pour les projets Django : http://south.aeracode.org/
    Je n'ai pas testé, donc je ne sais pas si c'est facilement applicable à n'importe quel projet/langage.

    Source : l'excellent blog de Carl Chenet, http://carlchenet.com/2013/06/08/technologies-derriere-un-site-web-a-base-de-django-aujourdhui/

    • [^] # Re: South

      Posté par (page perso) . Évalué à 1.

      Salut,

      Effectivement, pour Django il y a South.

      Pour SQLAlchemy (toujours en Python), tu peux utiliser Alembic : https://bitbucket.org/zzzeek/alembic

      Pour les autres langages et les autres bibliothèques, il faut utiliser les équivalents (si ça existe ; je n'en connais pas)…

      https://www.domotego.com/ | https://www.maccagnoni.eu/ | https://www.smm-informatique.fr/

      • [^] # Re: South

        Posté par . Évalué à 1.

        Salut, à tous !!!

        Je le dis dans ce fil, mais franchement merci à tous ! c'est vachement sympa
        J'ai regardé South, ça a l'air classe !
        En revanche c'est du python… Et pour anticiper la réponse que je donnerais plus loin, ça me gène un peu de multiplier les langages (déjà que j'en utilise pas mal)

        C'est un projet développé en PHP/MYSQL avec une interface web en HTML/JQUERY
        Il y a en plus bcp de sous-programmes en shell et en PERL (trop nombreux à dénombrer) qui attaquent la base de données et l'interface web via une API HTTP REST/FULL
        Ajoutons à ça toute la partie système linux debian: init.d, runit, logrotate, fail2ban, inotify, etc

        Alors tant qu'à faire… si ça pouvait s'adapter à mon projet en utilisant le même language :-)

  • # ça dépend

    Posté par (page perso) . Évalué à 2.

    Effectivement ça dépend un peu des besoins …
    mais je me pose aussi la question …

    il y a des solutions liée au langage de l'appli, Doctrine Migration pour php et doctrine, Ruby on Rail a ça built-in je pense, django voir au dessu, …

    sinon il y a des truc comme sqitch …. ou liquidbase …. mais de nouveaux ça dépend des besoins ….
    en gros j'ai identifié +- 2 technique :

    1. on décrit le model , et on le modifie sous un language intérmédiare (genre yaml, …) et là un outil fait tout pour toi , génère des "migrations", …
    2. on décrit son modèle en sql , et on fait une série de "migration" up et down qui seront appliquée ou pas par un outil …

  • # Déjà, qu'utilises-tu pour ton projet ? Langage/framewwork ?

    Posté par . Évalué à 2.

    Les solutions à ton problème sont liées à ça. Par exemple, Ruby on Rails utilise Active Records pour gérer les modifications de base de façon assez transparente, et tu peux utiliser Active Records en dehors de Rails. Il doit y avoir des équivalents dans le langage que tu utilises.

    • [^] # Re: Déjà, qu'utilises-tu pour ton projet ? Langage/framewwork ?

      Posté par . Évalué à 1.

      Comme je le disais plus haut (je me répète mais c'est pour garder la cohérence dans vos questions et mes réponses)

      C'est un projet développé en PHP/MYSQL avec une interface web en HTML/JQUERY
      Il y a en plus bcp de sous-programmes en shell et en PERL (trop nombreux à dénombrer) qui attaquent la base de données et l'interface web via une API HTTP REST/FULL
      Ajoutons à ça toute la partie système linux debian: init.d, runit, logrotate, fail2ban, inotify, etc

      Alors tant qu'à faire… si ça pouvait s'adapter à mon projet en utilisant le même language :-) Mais lequel ?????

      A vrai dire tous mes scripts de déploiement et de montées de version applicatives sont réalisés via des scripts bash, ce serait le language idéal à mon sens .
      Est-ce qu'il existe des scripts shell communautaire? des exemples pour gérer ça ? faudra t'il que je me le paluche à la mano ??

  • # Solution pour une base MySQL.. que je m'étais inventé pour un projet pas open source

    Posté par (page perso) . Évalué à 3.

    J'ai eu le même problème que toi sur un projet professionnel, je voulais maitriser les évolutions de mon schéma de base de donnée, et je m'étais organisé de manière assez similaire à toi mais en poussant un peu plus les version :

    • versioning dans SVN du shéma officiel en SQL avec TAG (crée avec MySQL Workbench) sous la forme d'un module
    • création d'une table appelée "version" avec pour premier champ la version correspondante… peut être qu'il serait plus logique à des fins de maintenance de pister la migration qui a coincé
    • A chaque nouvelle version du schéma je créais un fichier SQL d'upgrade du shéma de la version précédente vers la nouvelle version, en général je mettais à jour le fichier à chaque fois que je modifiais le schéma de référence.

    Par exemple, si dans mon cheminement de version j'avais une 1.1 puis une 1.2 et une 1.3

    Je me retrouvais avec les fichiers suivant :
    - upgrade1.1To1.2.sql
    - upgrade1.2To1.3.sql
    - shema.sql

    Lors de l'éxécution du setup d'upgrade, tout d'abord, je sauvegardais le schéma actuel, puis je détectais la installé, de manière à exécuter les scripts d'upgrade consécutif de manière à atteindre la bonne version de schéma.

    L'intéret de ces scripts, c'est qu'ils sont très facile à recetter de manière unitaire, il suffit de prendre le schéma de la version précédente (à vide) d'exécuter les scripts d'upgrade d'exporter la structure SQL générée et de la comparer avec le schéma officiel de la version.

  • # Pourquoi n'allez vous pas voir ce que j'ai fait pour vous en faire une idée ?

    Posté par . Évalué à 1.

    J'aurais peut être du commencer par ça :-)

    Je développe une application dédiée à la domotique -> http://wiseflat.com

    Pour vous donner une idée plus concrète de l'organisation de mon programme vous pouvez regarder ce schéma :
    Architecture du système

    Ce programme fonctionne sur plusieurs serveurs ( n'importe quoi, mais des serveurs basses consommations c'est plus chouette).
    Si je venais poser cette question c'est pour le "Manager" car c'est sur ce serveur que j'ai installé la base de données. Et donc gérer les montées de versions de la DB.

    Alors non ! ce que j'ai fait n'est pas une usine à gaz :-) même si ça y ressemble quand on regarde mon schéma

    Le 1er script d'installation c'est celui là installer

    Il propose d'installer le CORE, le MANAGER, ou la VOIX

    Allez donc jeter un coup d'oeil dans celui là : install_Manager

    Le plus simple est sûrement de garder ma logique de départ : faire une requête dans la table "version", récupérer le numéro de la version et exécuter les scripts un par un des différentes évolutions au cas où le "client" à n versions de retard…

    Remarque subsidiaire, j'aurais bcp aimé bosser sur des paquet deb, ou rpm pour gérer les contraintes de version des paquets perl, et les autres… Mais manque de temps j'ai jamais travaillé dessus pour le moment.

    D'autres programmeurs open-source utilisant une base de données mysql ce sont forcément posés la même question que moi, peut être même qu'ils ont géré ce cas là …

    A vous de me dire :-)
    Et merci bcp pour votre participation !

    • [^] # Re: Pourquoi n'allez vous pas voir ce que j'ai fait pour vous en faire une idée ?

      Posté par (page perso) . Évalué à 2.

      ton principal souci c'est de faire évoluer la bdd (sans perdre les données) lorsque ton programme monte en version

      ça signifie :
      1- il faut être capable d'identifier de façon certaine la version de bdd qui est en cours d'utilisation (table version, ou md5 du schéma)
      2- être capable d'appliquer toutes les modifications entre cette version et la version qui est en cours d'installation
      et le pire, c'est que si un utilisateur a sauté 1 ou plusieurs versions, tu dois être capable d'appliquer plusieurs patches sur le schéma de la bdd

      le point 2 va te contraindre à garder la trace (dans ton svn ou ailleurs) de toutes les versions de bdd des paquets que tu auras mis à disposition

      voilà comment je procéderai :

      • à chaque nouvelle version stable de bdd (correspondant à une version de mon paquet d'installation) je générerai un script de migration (en m'aidant d'outils comme MySQL Workbench, mysqldiff, etc)
      • avec chaque paquet, je livrerai tous les scripts de màj depuis la première version de bdd,
      • à chaque installation j'appliquerai tous ces scripts dans l'ordre

      une autre façon de faire serait :

      • faire un export des données
      • supprimer la bdd
      • recréer la bdd dans la dernière version connue
      • ré-importer les données

      au lieu d'avoir à gérer des scripts de màj de bdd, il faut gérer des versions différentes de format d'export/import
      c'est peut-être plus simple, je ne sais pas..

      Envoyé depuis mon Archlinux

      • [^] # Re: Pourquoi n'allez vous pas voir ce que j'ai fait pour vous en faire une idée ?

        Posté par . Évalué à 1.

        Génial…
        MySQL Workbench c'est juste un peu trop lourd pour moi, mysqldiff me semble l'idéal.
        Existe t'il la même chose sans interface graphique :-) ????? héhé

        J'aime bien la méthode des scripts d'upgrade
        Les imports/exports ça me fait un peu peur, surtout lors de l'import à cause des clefs étrangères et primaires.
        C'est aussi parce que par expérience, en prod on a tjrs des emmerdes à cause des violation de contraintes lors des mises à jour des livrables
        c'est peut être aussi parce que nos développeurs sont des burnes qui savent pas ce que c'est que la production et l'exploitation… mais chut, le répétez pas

        Mouais…donc mon idée de départ semble être la bonne

        • [^] # Re: Pourquoi n'allez vous pas voir ce que j'ai fait pour vous en faire une idée ?

          Posté par (page perso) . Évalué à 3.

          Tu fais des scripts à la main intitulés comme proposé ci-dessus :

          upgrade_1.2.3_to_1.2.4.sql
          upgrade_1.2.4_to_1.2.5.sql
          ...

          Tu les appliques les uns à la suite des autres. Si tu as des gros volumes de données, tu fais bien attention à ne pas faire des scripts d'upgrade qui prennent des heures (potentiellement bloquant si tu es en prod).

          Tu évites les outils automatiques parce que bien souvent ils te masquent une complexité que tu as besoin de connaître (en tout cas dans les premières étapes) ce qui fait qu'en cas de problème tu te retrouves "perdu".

          Tu ne fais pas des export/import : c'est moche ;)

          Et tu ne méprises pas ton équipe de développeurs mais tu les intéresses à ton métier : comme ça ils feront des outils et du dév qui te facilite de plus en plus la vie. C'est naturel que des dév. ne sachent pas ce que sont production et exploitation : ce n'est pas leur métier. A toi de leur faire découvrir (et de leur faire prendre en compte tes problématiques).

          • [^] # Re: Pourquoi n'allez vous pas voir ce que j'ai fait pour vous en faire une idée ?

            Posté par . Évalué à 0.

            Super merci pour ton conseil.

            C'est effectivement cette voix que j'ai choisi de suivre. Je ne gère pas d'outils automatique, ce ne sont que des scripts développés par mes soins donc je suis censé maitriser les phases de montées de versions….
            Il y aura surement des fois où l'upgrade ne sera passera pas bien pour X raisons… il faudra alors faire un retour arrière et repasser l'export réalisé précédemment. Donc oui il faut que je fasse des exports/imports.

            Et pour ta dernière remarque, je ne peux que t'approuver. Je n'aurais pas du dire ça. Je suis dur avec mes développeurs… Et effectivement je me dois de les sensibiliser à ce contexte de production/d'exploitation.
            Ils le comprennent assez bien dans l'ensemble mais il faut du temps. Et ce n'est pas chose facile. Fut un temps où pour les pb de production, ils se connectaient directement en prod pour passer leur script de mise à jour… Ou voir même faire des installations "from scratch" qui consiste à faire un DROP du schéma et recommencer par des CREATE/INSERT… Mais maintenant ce n'est plus le cas et les choses avancent dans le bon sens.

            Souvent les projets sont développés en externe et les cahiers des charges de départs ne contiennent pas certaines des exigences liées à l'exploitation des environnements. Là nos chefs de projets n'y sont pour rien non plus. Mais c'est chiant de faire remonter au chef de projet que le CC n'a pas été analysé et relu par des exploitants.

            Enfin, c'est un long débat passionnant mais ce n'était pas le but de ce post. Merci tout de même pour tes remarques

  • # Liquibase

    Posté par (page perso) . Évalué à 2.

    Je n'ai pas encore eu l'occasion d'essayer alors je ne peux pas t'en parler davantage, mais je me suis rappelé que j'avais placé un lien pour gérer cet épineux problème dans mes favoris pour remettre ça à plus tard (comme d'hab …)

    Liquibase

  • # Il n'y pas de remède miracle

    Posté par (page perso) . Évalué à 3. Dernière modification le 15/09/13 à 15:31.

    Je viens vers vous pour savoir comment vous géreriez ce cas là.

    C'est une problématique très large, la réponse peut tenir en trois lignes… ou bien occuper une service de devs pendant plusieurs mois!

    En inglishe, cela s'appelle un «database scheme upgrade» et une «data migration» — juste pour t'aiguiller dans tes recherches.

    Pour définir ta stratégie, tu dois définir tes objectifs et faire la liste de tes contraintes. Voici quelques questions pour commencer.

    Pour définir tes objectifs:

    • Après la mise à jour de sa BD consécutive à la MÀJ de 1 à 2 de ton soft, l'utilisateur remarque que sa fonction préférée qui marchait très bien dans 1 ne marche pas dans 2. Il ne peut se permettre d'attendre une MÀJ et souhaite retourner à la version 1. Comment fait-il?

    • Les système en prod peuvent-ils avoir un downtime?

    Tes contraintes:

    • Quels sont les systèmes de BD supportés?

    • L'upgrade de BD se fait côté soft ou bien avec un script SQL/sh?

    • Qui fait l'upgrade (admin, utilisateur inexpérimenté?)

    • Ton nouveau schéma est-il un sur ensemble strict de l'ancien (cas facile)?

    • Que doit-il se passer si la version 1 de ton soft tourne sur une BD avec le schéma de la version 2?

    • [^] # Re: Il n'y pas de remède miracle

      Posté par . Évalué à 0.

      Whaou! ça c'est du conseil !

      Les objectifs

      - Après la mise à jour de sa BD consécutive à la MÀJ de 1 à 2 de ton soft, l'utilisateur remarque que sa fonction préférée qui marchait très bien dans 1 ne marche pas dans 2. Il ne peut se permettre d'attendre une MÀJ et souhaite retourner à la version 1. Comment fait-il?

      Effectivement, il ne peut pas faire de retour arrière. Pour le moment il est censé attendre une mise à jour corrective. Mais je pourrais le prévoir, d'ailleurs j'ai prévu plusieurs paramètres à mon script d'upgrade
      --install (pour l'installation initiale)
      --updade (pour la montée de version)
      --force-update (pour forcer la réinstallation de la même version, voire d'une version antérieure. Il suffira de fournir en paramètre le chemin de la sauvegarde de la version n-1)

      - Les système en prod peuvent-ils avoir un downtime?

      Arf.. j'avais pas pensé aux scénarios utilisateurs… si le système se met en mode maintenance pendant un scénario ça risque de merder. Donc ça c'est chiant.
      Je pourrais prévoir que l'update se fasse entre 2 scénarios. Une petite boucle dans mon script toutes les 10 secondes devrait faire l'affaire. Faut tester…

      Les contraintes:

      Quels sont les systèmes de BD supportés?

      Pour le moment c'est du mysql.

      L'upgrade de BD se fait côté soft ou bien avec un script SQL/sh?

      L'upgrade se fait via script sh/sql. Il est géré par un cron quotidien.

      Qui fait l'upgrade (admin, utilisateur inexpérimenté?)

      C'est un cron. L'upgrade est géré par le système tel qu'expliqué précédemment.

      Ton nouveau schéma est-il un sur ensemble strict de l'ancien (cas facile)?

      Je ne suis pas sur de comprendre cette remarque.
      Le fichier sql d'update se charge de créer des tables (ou d'en supprimer), de modifier des structures. et je n'ai pas utilisé de clé étrangères (pour le cas des violation de clé, etc)

      Que doit-il se passer si la version 1 de ton soft tourne sur une BD avec le schéma de la version 2?

      Je n'ai pas géré ce cas là car je pars du principe que toute nouvelle livraison contient forcément un Core, un Manager, Un Voice. Et elles doivent s'installer simultanément.


      C'est super, tes remarques sont très pertinentes. Je me rends compte de tous les cas que j'ai pu oublié dans ce contexte de système décentralisé.
      Ce que je peux te dire c'est donc que :

      Je développe mon projet sur mon ordi. Je le teste dans une VM (c'est ma qualif). Et je le teste chez moi ( c'est ma prod).
      Une fois que les corrections/évolutions me semblent intéressantes et stabilisées, je met en ligne les livrables.
      Aucun des scénarios utilisateurs ne pourront tourner au moment de la montée de version. Sauf si je gère une mise en pause de ces scénarios durant l'installation. raaa j'avais pas pensé à ça !!! Donc mon installation automatique ne pourra pas marcher. Sauf si j'impose à l'utilisateur une période de 10 minutes de mise en maintenance quotidienne du système.
      Et il faut forcément que le système (Core, Manager, Voice) se mette en mode maintenance en même temps pour se mettre à jour afin qu'il n'y ait pas de requête sur la base mysql.

      J'aimerai bien utiliser un système en cluster avec un système de fichier distribué, pour que le service mysql puisse démarrer sur n'importe quel noeud. Tous les noeuds se mettraient à jour les uns après les autres et redémarreraient. C'est chaud, faisable mais dangereux. Quoique terriblement GEEK.

      Voilà merci pour ton aide. Ca a été très instructif !

      • [^] # Re: Il n'y pas de remède miracle

        Posté par (page perso) . Évalué à 2. Dernière modification le 29/09/13 à 14:44.

        Whaou! ça c'est du conseil!

        Saytun site de qualitay ici ;)

        Ce qui est toujours important c'est de correctement définir la tâche qu'on veut accomplir: la problématique «màj de la version de la base de données» est une description de très haut niveau qu'il faut définir pour pouvoir l'implémenter: le plus important est donc de définir les critères de succès (écrire des phrases qui doivent être vraies lorsque le processus est terminé) et comme on peut rarement avoir une procédure qui donne des bons résultats dans tous les cas de figure il faut arbitrer pour déterminer ce qui est important et ce qui l'est moins.

        Ton nouveau schéma est-il un sur ensemble strict de l'ancien (cas facile)?

        Je ne suis pas sur de comprendre cette remarque.

        Ce que je veux dire est que dans le cas où la nouvelle version A' de ton schéma A diffère de la première seulement par l'ajout de tables et de colonnes (hors clef) tu es dans un cas favorable, nettement plus facile à traiter que le cas où tu dois changer la clef principale d'une table, détruire une table ou pratiquer une transformation non réversible sur tes données. C'est donc un type d'évolution à privilégier tant qu'il est possible, soit dans les màj soit déjà dans la conception de la bd.

        Voilà merci pour ton aide. Ca a été très instructif !

        Avec plaisir, bonne chance!

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.