web-dev-qa-db-fra.com

Comment puis-je mettre une base de données sous git (contrôle de version)?

Je suis en train de créer une application Web et je dois créer une branche pour d'importants changements. Le fait est que ces changements nécessitent des modifications du schéma de la base de données. J'aimerais donc également placer la base de données entière sous git.

Comment je fais ça? Existe-t-il un dossier spécifique que je peux conserver sous un référentiel git? Comment savoir lequel? Comment puis-je être sûr de mettre le bon dossier?

Je dois en être sûr, car ces modifications ne sont pas compatibles avec les versions antérieures. Je ne peux pas me permettre de foirer.

La base de données dans mon cas est PostgreSQL

Modifier:

Quelqu'un a suggéré de faire des sauvegardes et de placer le fichier de sauvegarde sous contrôle de version au lieu de la base de données. Pour être honnête, je trouve cela très difficile à avaler.

Il doit y avoir une meilleure façon.

Mise à jour:

OK, donc il n'y a pas de meilleure solution, mais je ne suis toujours pas convaincu, alors je vais changer un peu la question:

J'aimerais placer la base de données entière sous contrôle de version. Quel moteur de base de données puis-je utiliser pour pouvoir placer la base de données réelle sous contrôle de version au lieu de son vidage?

Sqlite serait-il convivial?

Comme il ne s’agit que de l’environnement de développement, je peux choisir la base de données de mon choix.

Edit2:

Ce que je veux vraiment, ce n'est pas suivre l'historique de mon développement, mais pouvoir passer de ma branche "nouveaux changements radicaux" à la "branche stable actuelle" et pouvoir par exemple résoudre certains bugs/problèmes, etc. branche stable. Telle que lorsque je change de branche, la base de données devient automatiquement comme par magie compatible avec la branche sur laquelle je suis actuellement. Je ne me soucie pas beaucoup des données réelles.

258
hasen

Prenez un vidage de la base de données et contrôlez la version à la place. De cette façon, c'est un fichier texte plat.

Personnellement, je vous suggère de conserver à la fois un vidage de données et un vidage de schéma. De cette façon, en utilisant diff, il devient assez facile de voir ce qui a changé dans le schéma de révision en révision.

Si vous apportez des modifications importantes, vous devez disposer d’une base de données secondaire sur laquelle vous apportez les modifications de schéma sans toucher à l’ancienne, car vous avez indiqué que vous créiez une branche.

131
X-Istence

Consultez Refactoring Databases ( http://databaserefactoring.com/ ) pour découvrir de nombreuses techniques permettant de maintenir votre base de données en parallèle avec les modifications de code.

Autant dire que vous posez les mauvaises questions. Au lieu de mettre votre base de données dans git, vous devez décomposer vos modifications en petites étapes vérifiables afin de pouvoir migrer/annuler les modifications de schéma facilement.

Si vous souhaitez une récupération totale, vous devez envisager d'archiver vos journaux WAL postgres et utiliser le PITR (récupération ponctuelle) pour relire/transférer des transactions dans des états de bon état connus.

48
Paul Lindner

Je commence à penser à une solution très simple, je ne sais pas pourquoi je n'y avais pas pensé avant !!

  • Dupliquez la base de données (le schéma et les données).
  • Dans la branche pour les nouvelles modifications majeures, changez simplement la configuration du projet pour utiliser la nouvelle base de données en double.

De cette façon, je peux changer de branche sans me soucier des modifications de schéma de base de données.

MODIFIER:

Par dupliquer, je veux dire créer une autre base de données avec un nom différent (comme my_db_2); ne pas faire une décharge ou quelque chose comme ça.

26
hasen

Utilisez quelque chose comme LiquiBase Cela vous permet de garder le contrôle de révision de vos fichiers Liquibase. vous pouvez baliser les modifications pour la production uniquement et faire en sorte que lb garde votre base de données à jour pour la production ou le développement (ou le système de votre choix).

19
zie

Il existe un grand projet appelé Migrations sous Doctrine qui a été construit uniquement à cette fin.

Son encore dans l'état alpha et construit pour php.

http://docs.doctrine-project.org/projects/doctrine-migrations/en/latest/index.html

6
Hakan Deryal

Face à un besoin similaire, voici ce que mes recherches sur les systèmes de contrôle de version de base de données ont révélé:

  1. Sqitch - Open Source basé sur Perl; disponible pour toutes les bases de données principales, y compris PostgreSQL https://github.com/sqitchers/sqitch
  2. Mahout - uniquement pour PostgreSQL; contrôle de version de schéma de base de données open source. https://github.com/cbbrowne/mahout
  3. Liquibase - un autre contrôle de version db open source sw. version gratuite de Datical. http://www.liquibase.org/index.html
  4. Datical - version commerciale de Liquibase - https://www.datical.com/
  5. Flyway de BoxFuse - commercial sw. https://flywaydb.org/
  6. Un autre projet open source https://gitlab.com/depesz/Versioning L'auteur fournit un guide ici: https://www.depesz.com/2010/08/22/versioning/
  7. Red Gate Change Automation - uniquement pour SQL Server. https://www.red-gate.com/products/sql-development/sql-change-automation/
4

Examinez le contrôle de source SQL RedGate.

http://www.red-gate.com/products/sql-development/sql-source-control/

Cet outil est un composant logiciel enfichable SQL Server Management Studio qui vous permettra de placer votre base de données sous contrôle de code source avec Git.

C'est un peu cher à 495 $ par utilisateur, mais il y a un essai gratuit de 28 jours disponible.

NOTE Je ne suis pas affilié à RedGate de quelque manière que ce soit.

3
CShark

J'ai rencontré cette question, car j'ai un problème similaire, quelque chose qui ressemble à une structure de répertoires basée sur une base de données, les fichiers ', et j'ai besoin de git pour le gérer. Il est distribué, à travers un nuage, en utilisant la réplication. Son point d'accès sera donc via MySQL.

L'essentiel des réponses ci-dessus semble suggérer de la même manière une solution alternative au problème posé, qui passe à côté de l'idée d'utiliser Git pour gérer quelque chose dans une base de données, je vais donc tenter de répondre à cette question.

Git est un système qui stocke essentiellement une base de données de deltas (différences), qui peut être réassemblé afin de reproduire un contexte. L’utilisation normale de git suppose que le contexte est un système de fichiers, et ces deltas sont des différences dans ce système de fichiers, mais en réalité tout git est une base de données hiérarchique de deltas (hiérarchique, car dans la plupart des cas, chaque delta est un commit avec au moins 1 les parents, disposés dans un arbre).

Tant que vous pouvez générer un delta, en théorie, git peut le stocker. Le problème est normalement que git s'attend à ce que le contexte, sur lequel il génère le delta, soit un système de fichiers. De même, lorsque vous extrayez un point de la hiérarchie git, il s'attend à générer un système de fichiers.

Si vous voulez gérer le changement, dans une base de données, vous avez 2 problèmes distincts, et je les aborderais séparément (si j'étais vous). Le premier est le schéma, le second les données (bien que dans votre question, vous déclariez que les données ne vous intéressent pas). Un problème que j’avais dans le passé était une base de données Dev et Prod, où Dev pouvait apporter des modifications incrémentielles au schéma. Ces modifications devaient être consignées dans CVS, puis propagées à la vie réelle, avec des ajouts à l’un des nombreux "statiques". les tables. Nous l'avons fait en disposant d'une troisième base de données, appelée Cruise, qui ne contenait que les données statiques. Le schéma de Dev et Cruise pouvait être comparé à tout moment. Nous avions un script pour extraire le diff de ces 2 fichiers et générer un fichier SQL contenant les instructions ALTER afin de l'appliquer. De même, toute nouvelle donnée peut être distillée dans un fichier SQL contenant des commandes INSERT. Tant que les champs et les tables sont uniquement ajoutés et jamais supprimés, le processus peut automatiser la génération des instructions SQL pour appliquer le delta.

Le mécanisme par lequel git génère des deltas est diff et le mécanisme par lequel il combine un ou plusieurs deltas avec un fichier s'appelle merge. Si vous pouvez trouver une méthode pour différencier et fusionner d'un contexte différent, git devrait fonctionner, mais comme cela a été discuté, vous préférerez peut-être un outil qui le fait pour vous. Ma première pensée pour résoudre ce problème est la suivante https://git-scm.com/book/fr/v2/Customizing-Git-Git-Configuration#External-Merge-and-Diff-Tools dont les détails comment remplacer l'outil de diff et de fusion interne de git. Je mettrai à jour cette réponse car je proposerai une meilleure solution au problème, mais dans mon cas, je m'attends à devoir gérer uniquement les modifications de données, dans la mesure où un magasin de fichiers basé sur une base de données peut changer, de sorte que ma solution peut ne pas être exactement ce dont vous avez besoin.

3
sibaz

Je veux faire quelque chose de similaire, ajouter les modifications de ma base de données à mon système de contrôle de version.

Je vais suivre les idées contenues dans ce billet de Vladimir Khorikov "Meilleures pratiques en matière de gestion de bases de données" . En résumé je vais

  • stocker à la fois son schéma et les données de référence dans un système de contrôle de source.
  • pour chaque modification, nous allons créer un script SQL séparé avec les modifications

Au cas où ça aiderait!

3
Ciges

J'ai publié un outil pour sqlite qui fait ce que vous demandez. Il utilise un pilote de diff personnalisé exploitant l'outil de projets sqlite 'sqldiff', les UUID en tant que clés primaires, et laisse le rowid sqlite vide. Il est toujours en alpha, les commentaires sont donc appréciés.

Postgres et mysql sont plus compliqués, car les données binaires sont conservées dans plusieurs fichiers et peuvent même ne pas être valides si vous pouviez les prendre en instantané.

https://github.com/cannadayr/git-sqlite

2
cannadayr

Vous ne pouvez pas le faire sans atomicity et vous ne pouvez pas l'obtenir sans utiliser pg_dump ou un système de fichiers snapshotting.

Mon instance de postgres est sur zfs, que je capture occasionnellement. C'est à peu près instantané et cohérent.

2
Dustin

Ce que vous voulez, dans l’esprit, est peut-être quelque chose comme Post Facto , qui stocke les versions d’une base de données dans une base de données. Vérifiez ceci présentation .

Le projet n’a apparemment jamais vraiment abouti, il ne vous aidera probablement pas tout de suite, mais c’est un concept intéressant. Je crains que cela ne soit très difficile, car même la version 1 devrait avoir tous les détails pour que les gens puissent faire confiance à leur travail.

2
Peter Eisentraut

Je pense que X-Istence est sur la bonne voie, mais vous pouvez apporter quelques améliorations supplémentaires à cette stratégie. Première utilisation:

$pg_dump --schema ... 

vider les tables, les séquences, etc. et placer ce fichier sous contrôle de version. Vous allez l'utiliser pour séparer les modifications de compatibilité entre vos branches.

Ensuite, effectuez un vidage des données pour l'ensemble de tables contenant la configuration requise pour que votre application fonctionne (devrait probablement ignorer les données utilisateur, etc.), comme le formulaire valeurs par défaut et autres données non modifiables par l'utilisateur. Vous pouvez le faire sélectivement en utilisant:

$pg_dump --table=.. <or> --exclude-table=..

C'est une bonne idée, car le référentiel peut devenir vraiment maladroit lorsque votre base de données atteint 100 Mo + lors d'un vidage de données complet. Une meilleure idée est de sauvegarder un ensemble plus minimal de données dont vous avez besoin pour tester votre application. Si vos données par défaut sont très volumineuses, cela peut quand même causer des problèmes.

Si vous devez absolument placer des sauvegardes complètes dans le référentiel, envisagez de le faire dans une branche en dehors de votre arborescence source. Un système de sauvegarde externe avec une référence au svn rev correspondant est probablement préférable pour cela cependant.

De plus, je suggère d'utiliser des dumps de format texte sur binaire à des fins de révision (du moins pour le schéma) car ils sont plus faciles à différencier. Vous pouvez toujours les compresser pour économiser de l'espace avant l'enregistrement.

Enfin, jetez un œil à si ce n’est déjà fait) (documentation de sauvegarde postgres . La façon dont vous commentez la sauvegarde de la base de données plutôt que le dump me fait me demander si vous envisagez des sauvegardes basées sur le système de fichiers (voir la section 23.2 pour les mises en garde).

1
Dana the Sane

C'est comme ça que je le fais:

Puisque vous avez le libre choix du type de base de données, utilisez une base de données basée sur des fichiers, comme par exemple. oiseau de feu.

Créez une base de données modèle contenant le schéma qui correspond à votre branche actuelle et stockez-la dans votre référentiel.

Lorsque vous exécutez votre application, créez par programme une copie de votre base de données modèle, stockez-la ailleurs et utilisez simplement cette copie.

De cette façon, vous pouvez placer votre schéma de base de données sous contrôle de version sans les données. Et si vous modifiez votre schéma, il vous suffit de modifier le modèle DB

1
RomCoo

Je recommanderais neXtep pour le contrôle de version de la base de données, il dispose d'une bonne documentation et de forums expliquant comment installer et les erreurs rencontrées. Je l’ai testé pour PostgreSQL 9.1 et 9.3, j’ai réussi à le faire fonctionner pour 9.1 mais pour 9.3 il ne semble pas fonctionner.

1
Jerry M Sunny

Cette question a pas mal répondu, mais j'aimerais compléter la réponse de X-Istence et Dana the Sane par une petite suggestion.

Tous les jours si vous avez besoin d'un contrôle de révision avec un certain degré de granularité, vous pouvez coupler le dump de texte des tables et du schéma avec un outil tel que rdiff-backup , qui effectue des sauvegardes incrémentielles. L'avantage est qu'au lieu de stocker des instantanés de sauvegardes quotidiennes, vous stockez simplement les différences par rapport au jour précédent.

Avec cela, vous bénéficiez à la fois du contrôle de la révision et vous ne perdez pas trop d’espace.

Dans tous les cas, utiliser git directement sur de gros fichiers plats qui changent très fréquemment n’est pas une bonne solution. Si votre base de données devient trop grosse, git rencontrera des problèmes pour gérer les fichiers.

1
unode

Stocker chaque niveau de modification de la base de données sous le contrôle de gestion de version git revient à pousser votre au complet base de données avec chaque commit et restaurant toute votre base de données à chaque pull. Si votre base de données est si sujette à des modifications cruciales et que vous ne pouvez pas vous permettre de les perdre, vous pouvez simplement mettre à jour votre pre_commit et . ) post_merge crochets. J'ai fait la même chose avec l'un de mes projets et vous pouvez trouver les directions ici .

1
AkiShankar

Nous exploitions un site Web social, sur une configuration LAMP standard. Nous avions un serveur Live, un serveur de test et un serveur de développement, ainsi que les ordinateurs des développeurs locaux. Tous ont été gérés en utilisant GIT.

Sur chaque machine, nous avions les fichiers PHP, mais également le service MySQL, ainsi qu'un dossier contenant des images que les utilisateurs pourraient télécharger. Le serveur Live comptait environ 100 Ko (!) Utilisateurs récurrents, le dump coûtait environ 2 Go (!), Le dossier Image environ 50 Go (!). Au moment de mon départ, notre serveur atteignait la limite de son processeur, Ram, et surtout, les limites de connexion réseau simultanées (nous avons même compilé notre propre version du pilote de la carte réseau pour maximiser le serveur "lol"). Nous ne pouvions pas (et vous ne devriez pas présumer avec votre site web) mettre 2 Go de données et 50 Go d’images dans GIT.

Pour gérer facilement tout cela sous GIT, nous ignorerions les dossiers binaires (les dossiers contenant les images) en insérant ces chemins de dossiers dans .gitignore. Nous avions également un dossier appelé SQL en dehors du chemin de la racine de la documentation Apache. Dans ce dossier SQL, nous placerions nos fichiers SQL des développeurs dans des numérotations incrémentielles (001.florianm.sql, 001.johns.sql, 002.florianm.sql, etc.). Ces fichiers SQL ont également été gérés par GIT. Le premier fichier SQL contiendrait en effet un grand ensemble de schémas de base de données. Nous n’ajoutons pas de données utilisateur dans GIT (par exemple, les enregistrements de la table users ou la table des commentaires), mais des données telles que les configurations, la topologie ou d’autres données spécifiques au site ont été conservées dans les fichiers SQL (et donc par GIT). Ce sont principalement les développeurs (qui connaissent le mieux le code) qui déterminent ce qui n'est pas géré par GIT en ce qui concerne le schéma et les données SQL.

Lorsqu'il est arrivé à une version, l'administrateur se connecte sur le serveur de développement, fusionne la branche active avec tous les développeurs et les branches nécessaires sur la machine de développement en une branche de mise à jour, puis la transmet au serveur de test. Sur le serveur de test, il vérifie si le processus de mise à jour pour le serveur Live est toujours valide et, successivement, pointe tout le trafic dans Apache vers un site de substitution, crée un dump de base de données, fait pointer le répertoire de travail de "live" à "update". ', exécute tous les nouveaux fichiers SQL dans mysql et redirige le trafic vers le site approprié. Lorsque toutes les parties prenantes ont accepté après avoir examiné le serveur de test, l'administrateur a procédé de la même manière, de serveur de test à serveur Live. Il fusionne ensuite la branche active du serveur de production avec la branche principale de tous les serveurs et redéfinit la base de toutes les branches actives. Les développeurs étaient eux-mêmes responsables de rebaser leurs filiales, mais ils savent généralement ce qu’ils font.

S'il y avait des problèmes sur le serveur de test, par exemple. les fusions avaient trop de conflits, puis le code a été rétabli (renvoyant la branche active à "live") et les fichiers SQL n'ont jamais été exécutés. Au moment où les fichiers SQL ont été exécutés, cela a été considéré comme une action irréversible à l'époque. Si les fichiers SQL ne fonctionnaient pas correctement, la base de données était restaurée à l'aide du cliché (et les développeurs l'avaient exclu pour avoir fourni des fichiers SQL mal testés).

Aujourd'hui, nous maintenons à la fois un dossier sql-up et un dossier sql-down, avec des noms de fichiers équivalents, dans lesquels les développeurs doivent vérifier que les fichiers de mise à niveau SQL peuvent être également rétrogradés. Cela pourrait finalement être exécuté avec un script bash, mais c’est une bonne idée si des yeux humains surveillaient en permanence le processus de mise à niveau.

Ce n'est pas génial, mais c'est gérable. J'espère que cela vous donnera un aperçu d'un site réel, pratique et à disponibilité relativement élevée. Que ce soit un peu démodé, mais toujours suivi.

1
Florian Mertens

Ce que je fais dans mes projets personnels, c’est que j’enregistre toute ma base de données dans une boîte de dépôt, puis que je pointe le flux de travail MAMP, WAMP pour pouvoir l’utiliser directement à partir de là. Mais c'est juste pour dev! Live sites utilise son propre serveur pour ce faire! :)

1
Marko

Je recherche la même fonctionnalité pour Postgres (ou les bases de données SQL en général) depuis un moment, mais je n’ai trouvé aucun outil suffisant (simple et intuitif). Ceci est probablement dû à la nature binaire de la manière dont les données sont stockées. Klonio semble idéal mais semble mort. Noms DB semble intéressant (et vivant). Regardez aussi Irmin (basé sur OCaml avec Git-properties).

Bien que cela ne réponde pas à la question car cela fonctionnerait avec Postgres, consultez la base de données Flur.ee . Il dispose d'une fonctionnalité "voyage dans le temps" qui vous permet d'interroger les données à partir d'un moment arbitraire. J'imagine qu'il devrait pouvoir fonctionner avec un modèle de "ramification".

Cette base de données a récemment été développée à des fins de blockchain. En raison de la nature des blockchains, les données doivent être enregistrées par incréments, ce qui correspond exactement au fonctionnement de git. Ils sont ciblant une version open-source au T2 2019 .

Comme chaque base de données Fluree est une blockchain, elle stocke l’historique complet de chaque transaction effectuée. Cela fait partie de la manière dont une blockchain garantit que les informations sont immuables et sécurisées .

1
Tails

Mise à jour du 26 août 2019:

Netlify CMS le fait avec GitHub, un exemple d'implémentation est disponible ici avec toutes les informations sur la manière dont ils l'ont implémenté netlify-cms-backend-github

0
Tuna

J'aimerais placer la base de données entière sous contrôle de version. Quel moteur de base de données puis-je utiliser pour pouvoir placer la base de données réelle sous contrôle de version au lieu de son vidage?

Ce n'est pas dépendant du moteur de base de données. Par Microsoft SQL Server, il existe de nombreux programmes de contrôle de version. Je ne pense pas que ce problème puisse être résolu avec git, vous devez utiliser un système de contrôle de version de schéma spécifique à pgsql. Je ne sais pas si une telle chose existe ou non ...

0
inf3rno

Voici ce que j'essaie de faire dans mes projets:

  • données distinctes et schéma et données par défaut.

La configuration de la base de données est stockée dans un fichier de configuration qui n'est pas sous contrôle de version (.gitignore)

La base de données par défaut (pour la configuration de nouveaux projets) est un simple fichier SQL sous contrôle de version.

Pour le schéma de base de données, créez un vidage de schéma de base de données sous le contrôle de version.

Le moyen le plus courant consiste à avoir des scripts de mise à jour contenant des instructions SQL (ALTER Table .. ou UPDATE). Vous devez également avoir un emplacement dans votre base de données où vous sauvegardez la version actuelle de votre schéma)

Jetez un coup d’œil à d’autres grands projets de base de données open source (piwik ou votre système cms préféré), ils utilisent tous des scripts de mise à jour (1.sql, 2.sql, 3.sh, 4.php.5.sql).

Mais ce travail prend énormément de temps. Vous devez créer et tester les scripts de mise à jour. Vous devez également exécuter un script de mise à jour commun qui compare la version et tous les scripts de mise à jour nécessaires.

Donc, théoriquement (et c’est ce que je cherche), vous pouvez vider le schéma de base de données après chaque modification (manuellement, conjob, git hooks (peut-être avant la validation)) (et créer des mises à jour uniquement dans certains cas très spéciaux)

Après cela, dans votre script de mise à jour commun (exécutez les scripts de mise à jour normaux, pour les cas particuliers), puis comparez les schémas (la base de données dump et current), puis générez automatiquement les instructions ALTER nessionnelles. Il existe quelques outils qui peuvent déjà faire cela, mais n’ont pas encore trouvé le bon.

0
key_

Utilisez un outil comme iBatis Migrations ( manuel , courte vidéo de tutoriel ) qui vous permet de contrôler les versions des modifications vous faites à une base de données tout au long du cycle de vie d'un projet, plutôt que la base de données elle-même.

Cela vous permet d’appliquer de manière sélective des modifications individuelles à différents environnements, de conserver un journal des modifications dans les environnements, de créer des scripts pour appliquer les modifications de A à N, d’annuler les modifications, etc.

0
matt b