Hibernate: hbm2ddl.auto = mise à jour en production?

339

Est-il correct d'exécuter des applications Hibernate configurées avec hbm2ddl.auto=updatepour mettre à jour le schéma de base de données dans un environnement de production?

cretzel
la source
6
Nous le faisons. Jamais eu de problèmes.
cretzel
4
Très bonne question. J'y fais face maintenant. Alors maintenant 2018 - après 10 ans, quelle est votre opinion? Est-il sûr d'utiliser la mise à jour d'Hibernate sur les bases de données de production de clients importants avec des schémas complexes?
Kirill Ch

Réponses:

388

Non, c'est dangereux.

Malgré les meilleurs efforts de l'équipe Hibernate, vous ne pouvez tout simplement pas vous fier aux mises à jour automatiques en production . Écrivez vos propres correctifs, examinez-les avec DBA, testez-les, puis appliquez-les manuellement.

Théoriquement, si la mise à jour hbm2ddl fonctionnait en développement, elle devrait également fonctionner en production. Mais en réalité, ce n'est pas toujours le cas.

Même si cela fonctionnait bien, il pourrait ne pas être optimal. Les DBA sont payés autant pour une raison.

Vladimir Dyuzhev
la source
33
Pourquoi est-ce dangereux?
cretzel
74
C'est dangereux car les correctifs appliqués peuvent avoir des effets secondaires que hbm2ddl ne peut guère prédire (comme la désactivation des déclencheurs qui ont été installés pour la table en cours de modification). Pour les schémas complexes, le moyen le plus sûr est manuel. Automatique avec des tests de post-régression est loin derrière. Tous à mon humble avis.
Vladimir Dyuzhev
18
La mise à jour d'un schéma db doit également être gérée par les professionnels (dbas). La récupération d'un mauvais changement de base de données est au mieux difficile. Vova ne l'a pas mentionné - mais que se passe-t-il si la mise à jour d'Hibernate décide de supprimer une colonne et de la rajouter parce que le type ou la taille ont changé. Et disons que la colonne contient toutes les adresses e-mail de vos utilisateurs? :-) bye, bye company ..... Vous voulez que le changement DDL soit généré automatiquement - mais vous voulez absolument que le changement soit inspecté par un humain.
Pat
9
ne sauvegardez-vous pas vos bases de données avant une mise à niveau?
Jacob
21
Fwiw, pour le moment, la mise à jour du schéma d'Hibernate ne supprime pas les tables ou les colonnes.
Brian Deterling
70

Nous le faisons en production, bien qu'avec une application qui ne soit pas critique pour la mission et sans DBA hautement rémunéré sur le personnel. C'est juste un processus manuel de moins qui est sujet à une erreur humaine - l'application peut détecter la différence et faire la bonne chose, et vous l'avez probablement testée dans divers environnements de développement et de test.

Une mise en garde - dans un environnement en cluster, vous voudrez peut-être l'éviter car plusieurs applications peuvent apparaître en même temps et essayer de modifier le schéma, ce qui pourrait être mauvais. Ou mettez dans un mécanisme où une seule instance est autorisée à mettre à jour le schéma.

Brian Deterling
la source
2
Nous l'utilisons également en production, cas d'utilisation similaire. Plateforme d'analyse qui n'est pas critique pour la mission. Nous avons déployé 16 000 fois sur 4 environnements (4 ans) sans trop de hic avec hibernation. Nous sommes une petite équipe et sommes tous principalement des débutants SQL RDBS et avons une meilleure foi dans le schéma de gestion Hibernate que nous-mêmes. Je me demande quel est le taux d'erreur pour avoir un DBA sur le personnel gérant les migrations et les changements de schéma? Est-ce mieux que 0 dans ~ 16K déploiements?
user3263752
Que diriez-vous de ce commentaire par pat? stackoverflow.com/questions/221379/…
Shiva kumar
52

Les créateurs d'Hibernate déconseillent de le faire dans un environnement de production dans leur livre "Java Persistence with Hibernate" :

AVERTISSEMENT: nous avons vu des utilisateurs d'Hibernate essayer d'utiliser SchemaUpdate pour mettre à jour automatiquement le schéma d'une base de données de production. Cela peut rapidement se terminer en cas de catastrophe et ne sera pas autorisé par votre administrateur de base de données.

romain
la source
1
Cela a-t-il été écrit en 2006?
user3263752
28

Consultez LiquiBase XML pour conserver un journal des mises à jour. Je ne l'avais jamais utilisé avant cette année, mais j'ai trouvé qu'il était très facile à apprendre et à rendre le contrôle de révision / migration / gestion des modifications de base de données très infaillible. Je travaille sur un projet Groovy / Grails, et Grails utilise Hibernate en dessous pour tout son ORM (appelé "GORM"). Nous utilisons Liquibase pour gérer toutes les modifications de schéma SQL, ce que nous faisons assez souvent à mesure que notre application évolue avec de nouvelles fonctionnalités.

Fondamentalement, vous conservez un fichier XML de modifications que vous continuez d'ajouter à mesure que votre application évolue. Ce fichier est conservé dans git (ou tout ce que vous utilisez) avec le reste de votre projet. Lorsque votre application est déployée, Liquibase vérifie sa table de journal des modifications dans la base de données à laquelle vous vous connectez afin de savoir ce qui a déjà été appliqué, puis il applique intelligemment les changements qui n'ont pas encore été appliqués à partir du fichier. Cela fonctionne très bien dans la pratique, et si vous l'utilisez pour toutes vos modifications de schéma, vous pouvez être sûr à 100% que le code que vous retirez et déployez sera toujours en mesure de se connecter à un schéma de base de données entièrement compatible.

Ce qui est génial, c'est que je peux prendre une base de données mysql complètement vierge sur mon ordinateur portable, lancer l'application et tout de suite le schéma est configuré pour moi. Il permet également de tester facilement les modifications de schéma en les appliquant d'abord à un développeur local ou à une base de données intermédiaire.

Le moyen le plus simple de commencer serait probablement de prendre votre base de données existante, puis d'utiliser Liquibase pour générer un fichier baseline.xml initial. À l'avenir, vous pourrez simplement y ajouter et laisser Liquibase prendre en charge la gestion des modifications de schéma.

http://www.liquibase.org/

jpswain
la source
Parfait, juste ce que j'allais changer. Je pense que la meilleure chose, faire un pas en avant serait d'ajouter hbm2ddl.auto=updatepour que vos mappages de classe / DB soient validés et que vous ayez un contrôle complet de la création de DB via liquibase. Qu'est-ce que tu penses?
bholagabbar
Oups, je voulais direvalidate
bholagabbar
liquibase gère mieux les scripts en utilisant le support "include-import" comme le support et le support de version et l'attribut "Type" pour les fichiers, ce qui vous aide à avoir différents fichiers SQL pour différents environnements ayant une relation parent-enfant. en un mot, Go Traditional SQL Mgmt. en production. Pour le développement, nous avons besoin de vitesse pour la production, nous avons besoin de garanties et de stabilité et de sauvegarde.
Karan Kaw
26

Je voterais non. Hibernate ne semble pas comprendre quand les types de données des colonnes ont changé. Exemples (en utilisant MySQL):

String with @Column(length=50)  ==> varchar(50)
changed to
String with @Column(length=100) ==> still varchar(50), not changed to varchar(100)

@Temporal(TemporalType.TIMESTAMP,TIME,DATE) will not update the DB columns if changed

Il existe probablement d'autres exemples également, tels que l'augmentation de la longueur d'une colonne String sur 255 et sa conversion en texte, texte moyen, etc.

Certes, je ne pense pas qu'il existe vraiment un moyen de "convertir les types de données" sans créer une nouvelle colonne, copier les données et effacer l'ancienne colonne. Mais à la minute où votre base de données contient des colonnes qui ne reflètent pas le mappage Hibernate actuel, vous vivez très dangereusement ...

La voie de migration est une bonne option pour résoudre ce problème:

http://flywaydb.org

cliff.meyers
la source
1
Je viens d'essayer la première partie de votre exemple - dans mon cas, je passe @Column(length = 45)à @Column(length = 255). Peut vérifier qu'Hibernate 4.3.6.Final a correctement mis à jour le schéma de base de données à l'aide de hbm2ddl.auto=update. (Une chose à mentionner est que la base de données ne contient actuellement aucune donnée - seulement la structure.)
Steve Chambers
Il est très possible qu'ils aient corrigé ce bogue quelque part au cours des 6 dernières années environ. Cependant, si vous aviez des données dans le schéma et avez effectué une modification qui a entraîné une diminution de la largeur de colonne, vous allez rencontrer des erreurs ou une troncature de données non gérée.
cliff.meyers
1
flywaydb a besoin d'un script SQL conçu manuellement, il devrait être meilleur que ce qu'un programme automatique peut faire mais qui pourrait écrire un gros script, alors c'est un problème.
Bằng Rikimaru
25

Hibernate doit mettre en garde sur le fait de ne pas utiliser les mises à jour automatiques dans prod pour se couvrir lorsque des personnes qui ne savent pas ce qu'elles font l'utilisent dans des situations où elles ne devraient pas être utilisées.

Certes, les situations où il ne devrait pas être utilisé sont beaucoup plus nombreuses que celles où il est OK.

Je l'utilise depuis des années sur de nombreux projets différents et je n'ai jamais eu un seul problème. Ce n'est pas une réponse boiteuse, et ce n'est pas du codage cowboy. C'est un fait historique.

Une personne qui dit "ne jamais le faire en production" pense à un ensemble spécifique de déploiements de production, à savoir ceux qu'il connaît (son entreprise, son industrie, etc.).

L'univers des «déploiements de production» est vaste et varié.

Un développeur Hibernate expérimenté sait exactement ce que DDL va résulter d'une configuration de mappage donnée. Tant que vous testez et validez que ce que vous attendez se retrouve dans la DDL (en dev, qa, staging, etc.), tout va bien.

Lorsque vous ajoutez de nombreuses fonctionnalités, les mises à jour automatiques du schéma peuvent être un gain de temps réel.

La liste des choses que les mises à jour automatiques ne géreront pas est infinie, mais certains exemples sont la migration des données, l'ajout de colonnes non nullables, les changements de nom de colonne, etc., etc.

Vous devez également faire attention dans les environnements en cluster.

Mais là encore, si vous saviez tout cela, vous ne poseriez pas cette question. Hmm. . . OK, si vous posez cette question, vous devez attendre d'avoir beaucoup d'expérience avec Hibernate et les mises à jour de schéma automatique avant de penser à l'utiliser dans prod.

john.stein
la source
19

Comme je l'ai expliqué dans cet article , ce n'est pas une bonne idée d'utiliser hbm2ddl.autoen production.

La seule façon de gérer le schéma de base de données consiste à utiliser des scripts de migration incrémentielle car:

  • les scripts résideront dans VCS le long de votre base de code. Lorsque vous extrayez une branche, vous recréez l'intégralité du schéma à partir de zéro.
  • les scripts incrémentiels peuvent être testés sur un serveur QA avant d'être appliqués en production
  • aucune intervention manuelle n'est nécessaire car les scripts peuvent être exécutés par Flyway , ce qui réduit la possibilité d'erreur humaine associée à l'exécution manuelle des scripts.

Même le Guide de l'utilisateur d'Hibernate vous conseille d'éviter d'utiliser l' hbm2ddloutil pour les environnements de production.

entrez la description de l'image ici

Vlad Mihalcea
la source
C'est une réponse parfaite et je suis d'accord avec elle. Mais je trouve vraiment l'idée de créer manuellement le premier script de base de données (ie V1_0__initial_script.sql dans le cas de l'exemple du lien). Existe-t-il un moyen de créer un script à partir de ma base de données de développement existante qu'Hibernate a créé pour moi et de stocker dans V1_0_intial_script.sql ??
HopeKing
1
Utilisez SchemaExportcomme démontré par ce cas de test .
Vlad Mihalcea
Merci. Je suis tombé sur un vidage de ligne unique "mysqldump -u root -p --no-data dbname> schema.sql". Y a-t-il un inconvénient à utiliser le vidage généré à partir de cela?
HopeKing
1
Il n'y a aucun problème à utiliser un vidage de base de données.
Vlad Mihalcea
8

Nous le faisons dans un projet en cours de production depuis des mois maintenant et n'avons jamais eu de problème jusqu'à présent. Gardez à l'esprit les 2 ingrédients nécessaires à cette recette:

  1. Concevez votre modèle d'objet avec une approche de compatibilité descendante, c'est-à-dire de désapprouver des objets et des attributs plutôt que de les supprimer / les modifier. Cela signifie que si vous devez changer le nom d'un objet ou d'un attribut, laissez l'ancien tel quel, ajoutez le nouveau et écrivez une sorte de script de migration. Si vous devez modifier une association entre des objets, si vous êtes déjà en production, cela signifie que votre conception était incorrecte en premier lieu, alors essayez de penser à une nouvelle façon d'exprimer la nouvelle relation, sans affecter les anciennes données.

  2. Sauvegardez toujours la base de données avant le déploiement.

Mon sentiment est - après avoir lu ce post - que 90% des personnes prenant part à cette discussion sont horrifiées juste à l'idée d'utiliser des automatisations comme celle-ci dans un environnement de production. Certains lancent le ballon au DBA. Prenez un moment pour considérer que tous les environnements de production ne fourniront pas un DBA et que peu d'équipes de développement sont en mesure d'en acheter un (au moins pour les projets de taille moyenne). Donc, si nous parlons d'équipes où tout le monde doit tout faire, le ballon est sur elles.

Dans ce cas, pourquoi ne pas simplement essayer d'avoir le meilleur des deux mondes? Des outils comme celui-ci sont là pour vous aider, ce qui, avec une conception et un plan minutieux, peut vous aider dans de nombreuses situations. Et croyez-moi, les administrateurs peuvent être difficiles à convaincre au départ, mais s'ils savent que le ballon n'est pas entre leurs mains, ils vont l'adorer.

Personnellement, je ne reviendrais jamais à écrire des scripts à la main pour étendre n'importe quel type de schéma, mais c'est juste mon opinion. Et après avoir commencé récemment à adopter des bases de données sans schéma NoSQL, je peux voir que plus que bientôt, toutes ces opérations basées sur un schéma appartiendront au passé, il vaut donc mieux commencer à changer de perspective et à regarder vers l'avenir.

chris
la source
4
Je ne suis pas d'accord sur le commentaire NoSQL. Il est certainement en augmentation et a sa place, mais il existe de nombreuses applications qui dépendent absolument de la conformité ACID pour l'intégrité des données avec la concurrence et les transactions que NoSQL ne peut tout simplement pas fournir.
jpswain
7

Je ne le risquerais pas car vous pourriez perdre des données qui auraient dû être préservées. hbm2ddl.auto = update est un moyen purement simple de maintenir votre base de données de développement à jour.

Jaap Coomans
la source
2
ne sauvegardez-vous pas vos bases de données avant une mise à niveau?
Jacob
6
Oui, bien sûr, mais la restauration à partir d'une sauvegarde demande beaucoup de travail. Cela ne vaut pas la peine de restaurer des sauvegardes lorsque vous pouvez également mettre à jour votre base de données de manière ordonnée.
Jaap Coomans
6
  • Dans mon cas (Hibernate 3.5.2, Postgresql, Ubuntu), le réglage hibernate.hbm2ddl.auto=updaten'a créé que de nouvelles tables et créé de nouvelles colonnes dans des tables déjà existantes.

  • Il n'a ni supprimé les tables, ni supprimé les colonnes, ni modifié les colonnes. Cela peut être appelé une option sûre, mais quelque chose comme hibernate.hbm2ddl.auto=create_tables add_columnscela serait plus clair.

user1027272
la source
6

Ce n'est pas sûr, ce n'est pas recommandé, mais c'est possible.

J'ai de l'expérience dans une application utilisant l'option de mise à jour automatique en production.

Eh bien, les principaux problèmes et risques rencontrés dans cette solution sont:

  • Déployer dans la mauvaise base de données . Si vous commettez l'erreur d'exécuter le serveur d'applications avec une ancienne version de l'application (EAR / WAR / etc) dans la mauvaise base de données ... Vous aurez beaucoup de nouvelles colonnes, tables, clés étrangères et erreurs. Le même problème peut survenir avec une simple erreur dans le fichier source de données (copier / coller du fichier et oublié de changer la base de données). En résumé, la situation peut être un désastre dans votre base de données.
  • Le serveur d'applications prend trop de temps pour démarrer . Cela se produit car Hibernate essaie de trouver toutes les tables / colonnes / etc créées à chaque démarrage de l'application. Il a besoin de savoir ce qui (table, colonne, etc.) doit être créé. Ce problème ne fera qu'empirer à mesure que les tables de base de données grandissent.
  • Les outils de base de données sont presque impossibles à utiliser . Pour créer des scripts DDL ou DML de base de données à exécuter avec une nouvelle version, vous devez penser à ce qui sera créé par la mise à jour automatique après le démarrage du serveur d'applications. Par exemple, si vous devez remplir une nouvelle colonne avec des données, vous devez démarrer le serveur d'applications, attendre la mise en veille prolongée de la nouvelle colonne et exécuter le script SQL uniquement après cela. Comme vous pouvez le voir, les outils de migration de base de données (comme Flyway, Liquibase, etc.) sont presque impossibles à utiliser avec la mise à jour automatique activée.
  • Les modifications de la base de données ne sont pas centralisées . Avec la possibilité qu'Hibernate crée des tables et tout le reste, il est difficile de regarder les changements sur la base de données dans chaque version de l'application, car la plupart d'entre eux sont effectués automatiquement.
  • Encourage les déchets sur la base de données . En raison de l'utilisation "facile" de la mise à jour automatique, il est possible que votre équipe néglige de supprimer les anciennes colonnes et les anciennes tables, car la mise à jour automatique en veille prolongée ne peut pas le faire.
  • Catastrophe imminente . Le risque imminent qu'une catastrophe se produise dans la production (comme certaines personnes mentionnées dans d'autres réponses). Même avec une application en cours d'exécution et mise à jour depuis des années, je ne pense pas que ce soit un choix sûr. Je ne me suis jamais senti en sécurité avec cette option utilisée.

Donc, je ne recommanderai pas d'utiliser la mise à jour automatique en production.

Si vous voulez vraiment utiliser la mise à jour automatique en production, je recommande:

  • Réseaux séparés . Votre environnement de test ne peut pas accéder à l'environnement homologue. Cela permet d'éviter qu'un déploiement qui était censé se trouver dans l'environnement de test modifie la base de données d'homologation.
  • Gérer l'ordre des scripts . Vous devez organiser vos scripts à exécuter avant votre déploiement (modification de la table de structure, suppression de table / colonnes) et le script après le déploiement (informations de remplissage pour les nouvelles colonnes / tables).

Et, différent des autres articles, je ne pense pas que la mise à jour automatique activée soit liée aux DBA "très bien payés" (comme mentionné dans d'autres articles). Les administrateurs de base de données ont plus de choses à faire que d'écrire des instructions SQL pour créer / modifier / supprimer des tables et des colonnes. Ces tâches quotidiennes simples peuvent être effectuées et automatisées par les développeurs et transmises uniquement à l'équipe DBA pour examen, sans avoir besoin qu'Hibernate et DBA soient "très bien payés" pour les écrire.

Dherik
la source
4

Non, ne le fais jamais. Hibernate ne gère pas la migration des données. Oui, cela rendra votre schéma correct, mais cela ne garantit pas que des données de production précieuses ne sont pas perdues dans le processus.

Robert
la source
4
  • En règle générale, les applications d'entreprise dans les grandes organisations s'exécutent avec des privilèges réduits.

  • Le nom d'utilisateur de la base de données peut ne pas avoir le DDLprivilège d'ajouter des colonnes, ce qui hbm2ddl.auto=updatenécessite.

Aniket Kulkarni
la source
c'est un problème que je rencontre fréquemment. Nous essayons d'utiliser hibernate pour la création initiale de bases de données, mais il n'est souvent pas possible de le faire.
Dan
5
Ce n'est pas un "problème", c'est une bonne chose.
Vladimir Dyuzhev
2

Je suis d'accord avec Vladimir. Les administrateurs de mon entreprise n'apprécieraient certainement pas si je proposais même un tel cours.

De plus, la création d'un script SQL au lieu de faire aveuglément confiance à Hibernate vous donne la possibilité de supprimer les champs qui ne sont plus utilisés. Hibernate ne fait pas ça.

Et je trouve que la comparaison du schéma de production avec le nouveau schéma vous donne un meilleur aperçu du wat que vous avez modifié dans le modèle de données. Vous le savez, bien sûr, parce que vous l'avez fait, mais maintenant vous voyez tous les changements en une seule fois. Même ceux qui vous font aller comme "What the diable?!".

Il existe des outils qui peuvent créer un delta de schéma pour vous, donc ce n'est même pas un travail difficile. Et puis vous savez exactement ce qui va se passer.

extranéon
la source
"Il existe des outils qui peuvent créer un delta de schéma pour vous": pourriez-vous indiquer certains de ces outils?
Daniel Cassidy
Je pense que apexsql.com/sql_tools_diff.asp fait cela, et peut-être plus d'applications. Je le fais généralement à la main en vidant le schéma et en différant (en utilisant diff).
extraneon du
2

Le schéma des applications peut évoluer dans le temps; si vous avez plusieurs installations, qui peuvent être dans des versions différentes, vous devriez avoir un moyen de vous assurer que votre application, une sorte d'outil ou de script est capable de migrer le schéma et les données d'une version pas à pas vers une suivante.

Avoir toute votre persévérance dans les mappages (ou annotations) Hibernate est un très bon moyen de contrôler l'évolution du schéma.

Vous devez considérer que l'évolution du schéma a plusieurs aspects à considérer:

  1. évolution du schéma de base de données en ajoutant plus de colonnes et de tables

  2. suppression d'anciennes colonnes, tables et relations

  3. remplir de nouvelles colonnes avec des valeurs par défaut

Les outils de mise en veille prolongée sont importants en particulier au cas où (comme dans mon expérience) vous avez différentes versions de la même application sur de nombreux types de bases de données différents.

Le point 3 est très sensible dans le cas où vous utilisez Hibernate, comme dans le cas où vous introduisez une nouvelle propriété booléenne ou numérique, si Hibernate trouvera une valeur nulle dans ces colonnes, si lèvera une exception.

Donc, ce que je ferais, c'est: utilisez effectivement la capacité des outils Hibernate de mise à jour du schéma, mais vous devez ajouter à côté de lui des rappels de maintenance de données et de schéma, comme pour remplir les valeurs par défaut, supprimer les colonnes qui ne sont plus utilisées, etc. De cette façon, vous obtenez les avantages (scripts de mise à jour du schéma indépendants de la base de données et évitez le codage dupliqué des mises à jour, dans la pérennité et dans les scripts) mais vous couvrez également tous les aspects de l'opération.

Ainsi, par exemple, si une mise à jour de version consiste simplement à ajouter une propriété à valeur varchar (d'où une colonne), qui peut par défaut être nulle, avec la mise à jour automatique, vous aurez terminé. Là où plus de complexité est nécessaire, plus de travail sera nécessaire.

Cela suppose que l'application mise à jour est capable de mettre à jour son schéma (cela peut être fait), ce qui signifie également qu'elle doit avoir les droits d'utilisateur pour le faire sur le schéma. Si la politique du client empêche cela (cas probable de Lizard Brain), vous devrez fournir les scripts spécifiques à la base de données.

Pietro Polsinelli
la source