Comment gérez-vous les bases de données en développement, en test et en production ?

StackOverflow https://stackoverflow.com/questions/6371

  •  08-06-2019
  •  | 
  •  

Question

J'ai eu du mal à trouver de bons exemples sur la façon de gérer les schémas de base de données et les données entre les serveurs de développement, de test et de production.

Voici notre configuration.Chaque développeur dispose d'une machine virtuelle exécutant notre application et la base de données MySQL.C'est leur bac à sable personnel pour faire ce qu'ils veulent.Actuellement, les développeurs apporteront une modification au schéma SQL et effectueront un vidage de la base de données dans un fichier texte qu'ils valideront dans SVN.

Nous souhaitons déployer un serveur de développement d'intégration continue qui exécutera toujours le dernier code validé.Si nous faisons cela maintenant, cela rechargera la base de données depuis SVN pour chaque build.

Nous avons un serveur de test (virtuel) qui exécute "les candidats de libération". Le déploiement sur le serveur de test est actuellement un processus très manuel et implique généralement de charger le dernier SQL de SVN et de le peaufiner.De plus, les données sur le serveur de test sont incohérentes.Vous vous retrouvez avec les données de test que le dernier développeur à valider avait sur son serveur sandbox.

Là où tout s’effondre, c’est le déploiement en production.Étant donné que nous ne pouvons pas écraser les données réelles par des données de test, cela implique de recréer manuellement toutes les modifications du schéma.S'il y a eu un grand nombre de modifications de schéma ou de scripts de conversion pour manipuler les données, cela peut devenir vraiment compliqué.

Si le problème concernait uniquement le schéma, ce serait un problème plus simple, mais il existe des données « de base » dans la base de données qui sont également mises à jour pendant le développement, telles que les métadonnées dans les tables de sécurité et d'autorisations.

C’est le plus grand obstacle que je vois à l’évolution vers une intégration continue et des constructions en une seule étape.Comment faire toi résoudre?


Une question complémentaire :comment suivre les versions de base de données afin de savoir quels scripts exécuter pour mettre à niveau une instance de base de données donnée ?Une table de versions comme Lance le mentionne ci-dessous est-elle la procédure standard ?


Merci pour la référence à Tarantino.Je ne suis pas dans un environnement .NET, mais j'ai trouvé leur Page wiki DataBaseChangeMangement être très utile.Surtout ça Présentation Powerpoint (.ppt)

Je vais écrire un script Python qui vérifie les noms de *.sql scripts dans un répertoire donné par rapport à une table de la base de données et exécute ceux qui n'y sont pas dans l'ordre en fonction d'un entier qui constitue la première partie du nom de fichier.Si c'est une solution assez simple, comme je pense que ce sera le cas, je la publierai ici.


J'ai un script fonctionnel pour cela.Il gère l'initialisation de la base de données si elle n'existe pas et exécute les scripts de mise à niveau si nécessaire.Il existe également des commutateurs permettant d'effacer une base de données existante et d'importer des données de test à partir d'un fichier.Il fait environ 200 lignes, donc je ne le publierai pas (même si je pourrais le mettre sur Pastebin s'il y a de l'intérêt).

Était-ce utile?

La solution

Il existe quelques bonnes options.Je n'utiliserais pas la stratégie "restaurer une sauvegarde".

  1. Créez un script pour toutes les modifications de votre schéma et demandez à votre serveur CI d'exécuter ces scripts sur la base de données.Ayez une table de versions pour garder une trace de la version actuelle de la base de données et n'exécutez les scripts que s'ils concernent une version plus récente.

  2. Utilisez une solution de migration.Ces solutions varient selon la langue, mais pour .NET, j'utilise Migrator.NET.Cela vous permet de versionner votre base de données et de passer d'une version à l'autre.Votre schéma est spécifié dans le code C#.

Autres conseils

Vos développeurs doivent écrire des scripts de modification (modification de schéma et de données) pour chaque bogue/fonctionnalité sur lesquels ils travaillent, et pas simplement transférer l'intégralité de la base de données dans le contrôle de code source.Ces scripts mettront à niveau la base de données de production actuelle vers la nouvelle version en développement.

Votre processus de construction peut restaurer une copie de la base de données de production dans un environnement approprié et y exécuter tous les scripts du contrôle de code source, ce qui mettra à jour la base de données vers la version actuelle.Nous le faisons quotidiennement pour nous assurer que tous les scripts fonctionnent correctement.

Jetez un œil à la façon dont Ruby on Rails fait cela.

Il existe d'abord ce qu'on appelle les fichiers de migration, qui transforment essentiellement le schéma et les données de la base de données de la version N vers la version N+1 (ou en cas de rétrogradation de la version N+1 vers N).La base de données contient un tableau qui indique la version actuelle.

Les bases de données de test sont toujours effacées avant les tests unitaires et remplies de données fixes provenant de fichiers.

Le livre Refactorisation des bases de données :Conception de base de données évolutive pourrait vous donner quelques idées sur la façon de gérer la base de données.Une version courte est également lisible sur http://martinfowler.com/articles/evodb.html

Dans un projet PHP+MySQL, le numéro de révision de la base de données est stocké dans la base de données, et lorsque le programme se connecte à la base de données, il vérifie d'abord la révision.Si le programme nécessite une révision différente, il ouvrira une page de mise à niveau de la base de données.Chaque mise à niveau est spécifiée dans le code PHP, qui modifiera le schéma de la base de données et migrera toutes les données existantes.

  • Nommez vos bases de données comme suit - db_dev , db_test , db_qa , db_prod (évidemment, vous ne devriez jamais coder en dur les noms de bases de données
  • Ainsi, vous seriez en mesure de déployer même les différents types de bases de données sur le même serveur physique (je ne le recommande pas, mais vous devrez peut-être le faire...si les ressources sont limitées)
  • Assurez-vous que vous pourrez déplacer automatiquement les données entre celles-ci
  • Séparez les scripts de création de base de données de la population = Il devrait toujours être possible de recréer la base de données à partir de zéro et de la remplir (à partir de l'ancienne version de la base de données ou d'une source de données externe
  • n'utilisez pas de chaînes de connexion codées en dur dans le code (même pas dans les fichiers de configuration) - utilisez dans les fichiers de configuration des modèles de chaînes de connexion, que vous remplissez dynamiquement, chaque reconfiguration de la couche d'application qui nécessite une recompilation est MAUVAISE
  • utilisez la gestion des versions de base de données et la gestion des versions des objets de base de données - si vous pouvez vous le permettre, utilisez des produits prêts à l'emploi, sinon développez quelque chose par vous-même
  • suivez chaque modification DDL et enregistrez-la dans une table historique ( exemple ici )
  • Sauvegardes QUOTIDIENNES !Testez à quelle vitesse vous seriez capable de restaurer quelque chose perdu à partir d'une sauvegarde (utilisez des scripts de restauration automatiques
  • même votre base de données DEV et PROD ont exactement le même script de création, vous aurez des problèmes avec les données, alors permettez aux développeurs de créer la copie exacte de prod et de jouer avec (je sais que je recevrai des inconvénients pour celui-ci, mais changez dans le l'état d'esprit et le processus commercial vous coûteront beaucoup moins cher lorsque la merde frappe le ventilateur - alors forcez les codeurs à souscrire légalement tout ce que cela fait, mais assurez-vous que celui-ci

C’est quelque chose dont je ne suis constamment pas satisfait – notre solution à ce problème.Pendant plusieurs années, nous avons maintenu un script de modification distinct pour chaque version.Ce script contiendrait les deltas de la dernière version de production.À chaque version de l'application, le numéro de version incrémentait, donnant quelque chose comme ce qui suit :

  • dbChanges_1.sql
  • dbChanges_2.sql
  • ...
  • dbChanges_n.sql

Cela a assez bien fonctionné jusqu'à ce que nous commencions à maintenir deux axes de développement :Trunk/Mainline pour les nouveaux développements et une branche de maintenance pour les corrections de bugs, les améliorations à court terme, etc.Inévitablement, le besoin s’est fait sentir d’apporter des modifications au schéma de la branche.À ce stade, nous avions déjà dbChanges_n+1.sql dans le Trunk, nous avons donc fini par utiliser un schéma comme celui-ci :

  • dbChanges_n.1.sql
  • dbChanges_n.2.sql
  • ...
  • dbChanges_n.3.sql

Encore une fois, cela a assez bien fonctionné, jusqu'à ce qu'un jour nous recherchions et voyions 42 scripts delta dans la ligne principale et 10 dans la branche.ARGH!

De nos jours, nous maintenons simplement un script delta et laissons SVN le versionner - c'est-à-direnous écrasons le script à chaque version.Et nous hésitons à apporter des modifications au schéma des branches.

Donc, je ne suis pas non plus satisfait de cela.J'aime beaucoup le concept de migration depuis Rails.Je suis devenu assez fasciné par LiquiBase.Il prend en charge le concept de refactorisation incrémentielle de bases de données.Cela vaut le détour et je l'examinerai en détail bientôt.Quelqu'un a-t-il une expérience avec ça ?Je serais très curieux de connaître vos résultats.

Vous pouvez également envisager d'utiliser un outil comme Comparaison SQL pour scripter la différence entre les différentes versions d'une base de données, vous permettant de migrer rapidement entre les versions

Nous avons une configuration très similaire à l'OP.

Les développeurs développent dans des VM avec des bases de données privées.

[Les développeurs s'engageront bientôt dans des branches privées]

Les tests sont exécutés sur différentes machines (en fait dans les VM hébergées sur un serveur) [sera bientôt exécuté par Hudson CI Server

Testez en chargeant le dump de référence dans la base de données.Appliquer les correctifs de schéma des développeurs puis appliquer les correctifs de données des développeurs

Exécutez ensuite des tests unitaires et système.

La production est déployée auprès des clients en tant qu'installateurs.

Ce que nous faisons :

Nous effectuons un vidage de schéma de notre base de données sandbox.Puis un dump de données SQL.Nous différons cela de la référence précédente.cette paire de deltas doit passer de n-1 à n.

nous configurons les dumps et les deltas.

Donc, pour installer la version N CLEAN, nous exécutons le dump dans une base de données vide.Pour patcher, appliquez les patchs intermédiaires.

(Juha a mentionné que l'idée de Rail d'avoir un tableau enregistrant la version actuelle de la base de données est une bonne idée et devrait rendre l'installation des mises à jour moins compliquée.)

Les deltas et les dumps doivent être examinés avant le test bêta.Je ne vois aucun moyen de contourner ce problème car j'ai vu des développeurs insérer eux-mêmes des comptes de test dans la base de données.

Vérifiez dbdeploy, des outils Java et .net sont déjà disponibles, vous pouvez suivre leurs normes pour la présentation des fichiers SQL et la table des versions de schéma et écrire votre version Python.

J'ai bien peur d'être d'accord avec d'autres affiches.Les développeurs doivent scripter leurs modifications.

Dans de nombreux cas, un simple ALTER TABLE ne fonctionnera pas, vous devez également modifier les données existantes - les développeurs doivent réfléchir aux migrations requises et s'assurer qu'elles sont correctement scriptées (bien sûr, vous devez tester cela attentivement à un moment donné. le cycle de publication).

De plus, si vous avez du sens, vous demanderez également à vos développeurs de scripter les restaurations de leurs modifications afin qu'elles puissent être annulées si nécessaire.Cela doit également être testé, pour garantir que leur restauration non seulement s'exécute sans erreur, mais laisse la base de données dans le même état qu'elle était auparavant (ce n'est pas toujours possible ou souhaitable, mais c'est une bonne règle la plupart du temps) .

Comment connecter cela à un serveur CI, je ne sais pas.Peut-être que votre serveur CI doit disposer d'un instantané de build connu, sur lequel il revient chaque nuit, puis applique toutes les modifications depuis lors.C'est probablement mieux, sinon un script de migration défectueux interrompra non seulement la version de cette nuit, mais également toutes les suivantes.

Si vous êtes dans l'environnement .NET, la solution est Tarantino.Il gère tout cela (y compris les scripts SQL à installer) dans une version NANT.

J'ai écrit un outil qui (en me connectant à Ouvrir DBDiff) compare les schémas de bases de données et vous proposera des scripts de migration.Si vous effectuez une modification qui supprime ou modifie des données, cela générera une erreur, mais fournira une suggestion pour le script (par ex.lorsqu'une colonne est manquante dans le nouveau schéma, il vérifiera si la colonne a été renommée et créera xx - script.sql.suggestion généré contenant une instruction de renommage).

http://code.google.com/p/migrationscriptgenerator/ SQL Server uniquement, j'en ai bien peur :( C'est aussi assez alpha, mais c'est TRÈS faible friction (surtout si vous le combinez avec Tarantino ou http://code.google.com/p/simplescriptrunner/)

La façon dont je l'utilise est d'avoir un projet de scripts SQL dans votre .sln.Vous disposez également d'une base de données db_next localement dans laquelle vous apportez vos modifications (à l'aide de Management Studio ou Exportation de schéma NHibernate ou LinqToSql CreateDatabase ou quelque chose).Ensuite, vous exécutez migrationscriptgenerator avec les bases de données _dev et _next, ce qui crée.les scripts de mise à jour SQL pour la migration.

Nous utilisons la ligne de commande mysql-diff:il génère une différence entre deux schémas de base de données (à partir d'une base de données en direct ou d'un script) sous forme de script ALTER.mysql-diff est exécuté au démarrage de l'application et si le schéma est modifié, il en rend compte au développeur.Ainsi, les développeurs n'ont pas besoin d'écrire les ALTER manuellement, les mises à jour du schéma s'effectuent de manière semi-automatique.

Pour la base de données Oracle, nous utilisons oracle-ddl2svn outils.

Cet outil a automatisé le processus suivant

  1. pour chaque schéma de base de données, obtenez les ddl du schéma
  2. mettez-le sous contrôle de version

modifications entre les instances résolues manuellement

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top