Sospensione: hbm2ddl.auto = aggiornamento in produzione?


339

Va bene eseguire le applicazioni Hibernate configurate hbm2ddl.auto=updateper aggiornare lo schema del database in un ambiente di produzione?


6
Noi lo facciamo. Non ho mai avuto problemi.
cretzel,

4
Ottima domanda Lo sto affrontando ora. Quindi ora 2018 - dopo 10 anni qual è la tua opinione? È sicuro utilizzare l'aggiornamento di Hibernate su importanti database di produzione del cliente con schemi complessi?
Kirill Ch,

Risposte:


388

No, non è sicuro.

Nonostante i migliori sforzi del team Hibernate, semplicemente non puoi fare affidamento sugli aggiornamenti automatici in produzione . Scrivi le tue patch, esaminale con DBA, testale, quindi applicale manualmente.

Teoricamente, se l'aggiornamento di hbm2ddl ha funzionato nello sviluppo, dovrebbe funzionare anche nella produzione. Ma in realtà non è sempre così.

Anche se ha funzionato bene, potrebbe non essere ottimale. I DBA vengono pagati così tanto per un motivo.


33
Perché non è sicuro?
cretzel,

74
Non è sicuro perché le patch applicate potrebbero avere effetti collaterali che hbm2ddl difficilmente può prevedere (come disabilitare i trigger installati per la modifica della tabella). Per schemi complessi il modo più sicuro è manuale. Automatico con test post-regressione è distante secondo. Tutto IMHO.
Vladimir Dyuzhev,

18
Anche l'aggiornamento di uno schema db dovrebbe essere gestito dai professionisti (dbas). Il recupero da una brutta modifica del db è difficile nella migliore delle ipotesi. Vova non l'ha menzionato, ma cosa succede se l'aggiornamento di Hibernate decide di eliminare una colonna e aggiungerla di nuovo perché il tipo o la dimensione sono cambiati. E diciamo che la colonna è tutti gli indirizzi email dei tuoi utenti? :-) ciao, ciao compagnia ..... Vuoi che il cambiamento DDL sia generato automaticamente - ma vuoi assolutamente che il cambiamento sia ispezionato da un essere umano.
Pat,

9
non eseguire il backup dei database prima di un aggiornamento?
Jacob,

21
A proposito, al momento l'aggiornamento dello schema di Hibernate non elimina tabelle o colonne.
Brian Deterling,

70

Lo facciamo in produzione anche se con un'applicazione non mission-critical e senza DBA altamente retribuiti per il personale. È solo un processo manuale in meno soggetto a errore umano: l'applicazione è in grado di rilevare la differenza e fare la cosa giusta, inoltre presumibilmente l'hai testata in vari ambienti di sviluppo e test.

Un avvertimento: in un ambiente cluster potresti volerlo evitare perché più app possono venire contemporaneamente e provare a modificare lo schema che potrebbe essere negativo. O inserire un meccanismo in cui solo un'istanza è autorizzata ad aggiornare lo schema.


2
Lo usiamo anche in produzione, caso d'uso simile. Piattaforma di analisi non critica. Abbiamo distribuito 16.000 volte su 4 ambienti (4 anni) senza troppi problemi con l'ibernazione. Siamo un piccolo team e siamo per lo più principianti di SQL RDBS e abbiamo una maggiore fiducia nello schema di gestione di Hibernate rispetto a noi stessi. Mi chiedo quale sia il tasso di errore per avere un DBA nel personale che gestisce le migrazioni e le modifiche dello schema? È meglio di 0 nelle distribuzioni di ~ 16K?
user3263752,

Cosa diresti su questo commento di Pat? stackoverflow.com/questions/221379/…
Shiva kumar il

52

I creatori di Hibernate scoraggiano farlo in un ambiente di produzione nel loro libro "Java Persistence with Hibernate" :

ATTENZIONE: abbiamo visto gli utenti di Hibernate tentare di utilizzare SchemaUpdate per aggiornare automaticamente lo schema di un database di produzione. Questo può rapidamente finire in un disastro e non sarà consentito dal tuo DBA.


1
È stato scritto nel 2006?
user3263752

28

Dai un'occhiata a LiquiBase XML per tenere un registro degli aggiornamenti. Non l'avevo mai usato fino a quest'anno, ma ho scoperto che è molto facile da imparare e rendere il controllo delle revisioni DB / migrazione / gestione delle modifiche molto infallibile. Lavoro a un progetto Groovy / Grails e Grails usa Hibernate per tutto il suo ORM (chiamato "GORM"). Utilizziamo Liquibase per gestire tutte le modifiche allo schema SQL, cosa che facciamo abbastanza spesso man mano che la nostra app si evolve con nuove funzionalità.

Fondamentalmente, mantieni un file XML di changeset che continui ad aggiungere man mano che la tua applicazione si evolve. Questo file è tenuto in git (o qualunque cosa tu stia usando) con il resto del tuo progetto. Quando la tua app viene distribuita, Liquibase controlla la sua tabella dei log nel DB a cui ti stai connettendo in modo che sappia cosa è già stato applicato, quindi applica in modo intelligente qualsiasi modifica che non sia stata ancora applicata dal file. In pratica funziona alla grande e, se lo usi per tutte le modifiche allo schema, puoi essere sicuro al 100% che il codice che esegui il checkout e la distribuzione sarà sempre in grado di connettersi a uno schema di database completamente compatibile.

La cosa fantastica è che posso prendere un database mysql di ardesia totalmente vuoto sul mio laptop, avviare l'app e subito lo schema è impostato per me. Inoltre, semplifica il test delle modifiche allo schema applicandole prima a un sviluppatore locale o alla gestione temporanea del db.

Il modo più semplice per iniziare sarebbe probabilmente quello di prendere il tuo DB esistente e quindi utilizzare Liquibase per generare un file iniziale baseline.xml. Quindi in futuro puoi semplicemente aggiungerlo e lasciare che la liquibase prenda il controllo della gestione delle modifiche dello schema.

http://www.liquibase.org/


Perfetto, proprio quello che stavo per passare. Sento la cosa migliore, fare un passo avanti sarebbe quello di aggiungere in hbm2ddl.auto=updatemodo che i tuoi mapping Class / DB siano validati e tu abbia il controllo completo della creazione di DB attraverso liquibase. Cosa ne pensi?
bholagabbar

Spiacenti, intendevovalidate
bholagabbar l'

liquibase è migliore nella gestione degli script usando il supporto "include-import" come il supporto di versione e l'attributo "Tipo" per i file che consente di avere diversi file SQL per diversi ambienti con relazione padre figlio. in poche parole, vai a SQL Mgmt tradizionale. in produzione. Per lo sviluppo, abbiamo bisogno di velocità per la produzione, abbiamo bisogno di garanzie, stabilità e backup.
Karan Kaw,

26

Vorrei votare no. Hibernate non sembra capire quando i tipi di dati per le colonne sono cambiati. Esempi (usando 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

Probabilmente ci sono anche altri esempi, come spingere la lunghezza di una colonna String su 255 e vederla convertire in testo, testo medio, ecc. Ecc.

Certo, non credo che ci sia davvero un modo per "convertire i tipi di dati" senza creare una nuova colonna, copiare i dati e spazzare via la vecchia colonna. Ma nel momento in cui il tuo database ha colonne che non riflettono l'attuale mappatura di Hibernate, stai vivendo molto pericolosamente ...

Flyway è una buona opzione per affrontare questo problema:

http://flywaydb.org


1
Ho appena provato la prima parte del tuo esempio, nel mio caso cambiando @Column(length = 45)in @Column(length = 255). Può verificare che Hibernate 4.3.6.Final abbia aggiornato correttamente lo schema del database usando hbm2ddl.auto=update. (Una cosa da menzionare è che al momento il database non contiene alcun dato - solo la struttura.)
Steve Chambers

È molto probabile che abbiano corretto quel bug da qualche parte negli ultimi circa 6 anni circa. Tuttavia, se si disponevano di dati nello schema e si è apportata una modifica che ha comportato una riduzione della larghezza della colonna, si verificheranno errori o troncamento dei dati non gestiti.
cliff.meyers,

1
flywaydb ha bisogno di uno script SQL creato manualmente, dovrebbe essere migliore di quello che può fare un programma automatico ma chi potrebbe scrivere uno script di grandi dimensioni, quindi è un problema.
Bằng Rikimaru,

25

Hibernate deve mettere il disclaimer sul non usare gli aggiornamenti automatici in prod per coprirsi quando le persone che non sanno cosa stanno facendo lo usano in situazioni in cui non dovrebbe essere usato.

Concesso le situazioni in cui non dovrebbe essere usato molto più di quelle in cui è OK.

L'ho usato per anni in molti progetti diversi e non ho mai avuto un singolo problema. Non è una risposta scadente e non è la codifica da cowboy. È un fatto storico.

Una persona che dice "non farlo mai in produzione" sta pensando a un insieme specifico di schieramenti di produzione, vale a dire quelli con cui ha familiarità (la sua azienda, la sua industria, ecc.).

L'universo delle "distribuzioni di produzione" è vasto e vario.

Uno sviluppatore Hibernate con esperienza sa esattamente quale sarà il risultato DDL da una determinata configurazione di mappatura. Finché testate e confermate che ciò che vi aspettate finisce nel DDL (in sviluppo, qa, messa in scena, ecc.), State bene.

Quando aggiungi molte funzionalità, gli aggiornamenti automatici dello schema possono farti risparmiare tempo reale.

L'elenco di cose che gli aggiornamenti automatici non gestiranno è infinito, ma alcuni esempi sono la migrazione dei dati, l'aggiunta di colonne non annullabili, le modifiche dei nomi delle colonne, ecc. Ecc.

Inoltre, è necessario prestare attenzione in ambienti cluster.

Ma poi di nuovo, se conoscessi tutta questa roba, non faresti questa domanda. Hmm . . OK, se stai ponendo questa domanda, dovresti aspettare fino a quando non avrai molta esperienza con Hibernate e gli aggiornamenti dello schema automatico prima di pensare di usarlo in prod.


19

Come ho spiegato in questo articolo , non è una buona idea usare hbm2ddl.autoin produzione.

L'unico modo per gestire lo schema del database è utilizzare gli script di migrazione incrementale perché:

  • gli script risiederanno in VCS lungo la tua base di codice. Quando si esegue il checkout di un ramo, si ricrea l'intero schema da zero.
  • gli script incrementali possono essere testati su un server QA prima di essere applicati in produzione
  • non è necessario un intervento manuale poiché gli script possono essere eseguiti da Flyway , quindi riduce la possibilità di errore umano associato all'esecuzione manuale degli script.

Anche la Guida dell'utente di Hibernate ti consiglia di evitare di utilizzare lo hbm2ddlstrumento per ambienti di produzione.

inserisci qui la descrizione dell'immagine


Questa è una risposta perfetta e sono d'accordo. Ma trovo davvero l'idea di creare manualmente il primo script di database ingombrante (cioè V1_0__initial_script.sql nel caso dell'esempio nel link). C'è un modo in cui posso creare uno script dal mio db di sviluppo esistente che Hibernate ha creato per me e archiviare in V1_0_intial_script.sql ??
HopeKing,

1
Utilizzare SchemaExportcome dimostrato da questo caso di test .
Vlad Mihalcea,

Grazie. Mi sono imbattuto in un dump a riga singola "mysqldump -u root -p --no-data nome_db> schema.sql". C'è qualche svantaggio nell'usare il dump generato da questo?
HopeKing

1
Non ci sono problemi usando un dump DB.
Vlad Mihalcea,

8

Lo facciamo in un progetto in esecuzione da mesi ormai e non abbiamo mai avuto problemi finora. Tieni presente i 2 ingredienti necessari per questa ricetta:

  1. Progetta il tuo modello a oggetti con un approccio di retrocompatibilità, ovvero deprecare oggetti e attributi anziché rimuoverli / alterarli. Ciò significa che se è necessario modificare il nome di un oggetto o di un attributo, lasciare quello vecchio così com'è, aggiungere quello nuovo e scrivere una sorta di script di migrazione. Se hai bisogno di cambiare un'associazione tra oggetti, se sei già in produzione, questo significa che il tuo design era in primo luogo sbagliato, quindi prova a pensare a un nuovo modo di esprimere la nuova relazione, senza influire sui vecchi dati.

  2. Eseguire sempre il backup del database prima della distribuzione.

Il mio senso è - dopo aver letto questo post - che il 90% delle persone che prendono parte a questa discussione sono inorriditi solo dal pensiero di usare automazioni come questa in un ambiente di produzione. Alcuni lanciano la palla al DBA. Prenditi un momento per considerare che non tutti gli ambienti di produzione forniranno un DBA e non molti team di sviluppatori sono in grado di permettersene uno (almeno per progetti di medie dimensioni). Quindi, se stiamo parlando di squadre in cui tutti devono fare tutto, la palla è su di loro.

In questo caso, perché non provare ad avere il meglio dei due mondi? Strumenti come questo sono qui per dare una mano, che - con una progettazione e un piano accurati - può aiutare in molte situazioni. E credetemi, inizialmente gli amministratori potrebbero essere difficili da convincere, ma se sanno che la palla non è nelle loro mani, lo adoreranno.

Personalmente, non tornerei mai più a scrivere script a mano per estendere qualsiasi tipo di schema, ma questa è solo la mia opinione. E dopo aver iniziato ad adottare database NoSQL senza schema di recente, posso vedere che più che presto, tutte queste operazioni basate su schemi apparterranno al passato, quindi è meglio iniziare a cambiare prospettiva e guardare avanti.


4
Non sono d'accordo sul commento NoSQL. È sicuramente in aumento e ha il suo posto, ma ci sono molte applicazioni che dipendono assolutamente dalla conformità ACID per l'integrità dei dati con la concorrenza e le transazioni che NoSQL semplicemente non può fornire.
jpswain,

7

Non rischierei perché potresti perdere dati che avrebbero dovuto essere conservati. hbm2ddl.auto = update è puramente un modo semplice per mantenere aggiornato il database degli sviluppatori.


2
non eseguire il backup dei database prima di un aggiornamento?
Jacob,

6
Sì, certo che lo faccio, ma è molto difficile ripristinare da un backup. Non vale la seccatura di ripristinare i backup quando è anche possibile aggiornare il database in modo ordinato.
Jaap Coomans,

6
  • Nel mio caso (Hibernate 3.5.2, Postgresql, Ubuntu), impostazione hibernate.hbm2ddl.auto=update creato solo nuove tabelle e creato nuove colonne in tabelle già esistenti.

  • Non ha lasciato cadere le tabelle, né le colonne, né le colonne modificate. Può essere definita un'opzione sicura, ma qualcosa di simile hibernate.hbm2ddl.auto=create_tables add_columnssarebbe più chiaro.


6

Non è sicuro, non raccomandato, ma è possibile.

Ho esperienza in un'applicazione che utilizza l'opzione di aggiornamento automatico in produzione.

Bene, i principali problemi e rischi riscontrati in questa soluzione sono:

  • Distribuire nel database errato . Se commetti l'errore di eseguire il server delle applicazioni con una versione precedente dell'applicazione (EAR / WAR / etc) nel database errato ... Avrai molte nuove colonne, tabelle, chiavi esterne ed errori. Lo stesso problema può verificarsi con un semplice errore nel file dell'origine dati (copia / incolla file e dimentica di cambiare il database). In ripresa, la situazione può essere un disastro nel database.
  • Il server delle applicazioni impiega troppo tempo per avviarsi . Ciò si verifica perché l'ibernazione tenta di trovare tutte le tabelle / colonne / etc create ogni volta che si avvia l'applicazione. Deve sapere cosa deve essere creato (tabella, colonna, ecc.). Questo problema peggiorerà man mano che crescono le tabelle del database.
  • Strumenti di database è quasi impossibile da usare . Per creare script DDL o DML del database da eseguire con una nuova versione, è necessario pensare a cosa verrà creato dall'aggiornamento automatico dopo aver avviato il server delle applicazioni. Ad esempio, se è necessario riempire una nuova colonna con alcuni dati, è necessario avviare il server delle applicazioni, attendere l'ibernazione per cancellare la nuova colonna ed eseguire lo script SQL solo dopo. Come puoi vedere, gli strumenti di migrazione del database (come Flyway, Liquibase, ecc.) Sono quasi impossibili da usare con l'aggiornamento automatico abilitato.
  • Le modifiche al database non sono centralizzate . Con la possibilità di Hibernate di creare tabelle e tutto il resto, è difficile guardare le modifiche al database in ogni versione dell'applicazione, poiché la maggior parte di esse viene effettuata automaticamente.
  • Incoraggia la spazzatura nel database . A causa dell'uso "facile" dell'aggiornamento automatico, è possibile che il tuo team trascuri di eliminare vecchie colonne e vecchie tabelle, poiché l'aggiornamento automatico ibernato non può farlo.
  • Disastro imminente . L'imminente rischio che si verifichi un disastro nella produzione (come alcune persone menzionate in altre risposte). Anche con un'applicazione in esecuzione e aggiornata da anni, non credo sia una scelta sicura. Non mi sono mai sentito al sicuro con questa opzione utilizzata.

Quindi, non consiglierò di utilizzare l'aggiornamento automatico in produzione.

Se vuoi davvero utilizzare l'aggiornamento automatico in produzione, ti consiglio di:

  • Reti separate . Il tuo ambiente di test non può accedere all'ambiente omologa. Ciò consente di impedire che una distribuzione che si suppone si trovi nell'ambiente di test cambi il database di omologazione.
  • Gestisci l'ordine degli script . È necessario organizzare gli script da eseguire prima della distribuzione (modifica della tabella della struttura, eliminazione della tabella / colonne) e script dopo la distribuzione (compilare le informazioni per le nuove colonne / tabelle).

E, a differenza degli altri post, non credo che l'aggiornamento automatico abbia consentito che sia correlato a DBA "molto ben pagati" (come menzionato in altri post). I DBA hanno cose più importanti da fare che scrivere istruzioni SQL per creare / modificare / eliminare tabelle e colonne. Queste semplici attività quotidiane possono essere eseguite e automatizzate dagli sviluppatori e passate solo al team DBA per la revisione, senza che Hibernate e DBA siano "molto ben pagati" per scriverle.


4

No, non farlo mai. Hibernate non gestisce la migrazione dei dati. Sì, farà apparire correttamente il tuo schema ma non garantisce che durante il processo non vengano persi preziosi dati di produzione.


4
  • In genere, le applicazioni aziendali in organizzazioni di grandi dimensioni vengono eseguite con privilegi ridotti.

  • Il nome utente del database potrebbe non avere il DDLprivilegio di aggiungere colonne che hbm2ddl.auto=updaterichiede.


questo è un problema che incontro frequentemente. Cerchiamo di utilizzare l'ibernazione per la creazione iniziale del DB ma spesso non è possibile farlo.
Dan,

5
Non è un "problema", questa è una cosa giusta.
Vladimir Dyuzhev,

2

Sono d'accordo con Vladimir. Gli amministratori della mia azienda non apprezzerebbero sicuramente se avessi anche suggerito un simile corso.

Inoltre, la creazione di uno script SQL al posto della fiducia cieca di Hibernate ti dà la possibilità di rimuovere i campi che non sono più in uso. Ibernazione non lo fa.

E trovo che il confronto dello schema di produzione con il nuovo schema ti offra una visione ancora migliore di ciò che hai cambiato nel modello di dati. Sai, ovviamente, perché ce l'hai fatta, ma ora vedi tutti i cambiamenti in una volta sola. Anche quelli che ti fanno andare come "Che diamine ?!".

Ci sono strumenti che possono creare un delta dello schema per te, quindi non è nemmeno un duro lavoro. E poi sai esattamente cosa succederà.


"Esistono strumenti che possono creare un delta dello schema per te": Potresti indicare alcuni di questi strumenti?
Daniel Cassidy,

Penso che apexsql.com/sql_tools_diff.asp faccia questo, e probabilmente altre app. Di solito lo faccio a mano scaricando lo schema e diffing (usando diff).
extraneon,

2

Lo schema delle applicazioni potrebbe evolversi nel tempo; se si dispone di più installazioni, che possono trovarsi in versioni diverse, è necessario disporre di un modo per garantire che l'applicazione, un qualche tipo di strumento o script sia in grado di migrare schemi e dati da una versione in modo graduale a una successiva.

Avere tutta la tua persistenza nelle mappature (o annotazioni) di Hibernate è un ottimo modo per tenere sotto controllo l'evoluzione dello schema.

Dovresti considerare che l'evoluzione dello schema ha diversi aspetti da considerare:

  1. evoluzione dello schema del database nell'aggiunta di più colonne e tabelle

  2. caduta di vecchie colonne, tabelle e relazioni

  3. riempire nuove colonne con valori predefiniti

Gli strumenti di ibernazione sono importanti in particolare nel caso (come nella mia esperienza) hai versioni diverse della stessa applicazione su molti tipi diversi di database.

Il punto 3 è molto sensibile nel caso in cui si utilizzi Hibernate, come nel caso in cui si introduca una nuova proprietà booleana valutata o numerica, se Hibernate troverà un valore nullo in tali colonne, se solleverà un'eccezione.

Quindi quello che vorrei fare è: utilizzare davvero la capacità degli strumenti di Hibernate di aggiornamento dello schema, ma è necessario aggiungere al suo fianco alcuni callback di manutenzione dei dati e dello schema, come per riempire i valori predefiniti, eliminare colonne non più utilizzate e simili. In questo modo si ottengono i vantaggi (script di aggiornamento dello schema indipendenti dal database ed evitando la duplicazione della codifica degli aggiornamenti, in peristenza e negli script) ma si coprono anche tutti gli aspetti dell'operazione.

Quindi, ad esempio, se un aggiornamento di versione consiste semplicemente nell'aggiunta di una proprietà con valore varchar (quindi colonna), che può essere impostata su null per impostazione predefinita, con l'aggiornamento automatico verrà eseguito. Laddove è necessaria una maggiore complessità, sarà necessario più lavoro.

Ciò presuppone che l'applicazione, una volta aggiornata, sia in grado di aggiornare il suo schema (è possibile farlo), il che significa anche che deve disporre dei diritti utente per farlo sullo schema. Se la politica del cliente lo impedisce (probabile caso Lizard Brain), dovrai fornire gli script specifici del database.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.