{"id":70973,"date":"2020-02-23T00:58:26","date_gmt":"2020-02-22T21:58:26","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase"},"modified":"2020-03-03T16:14:41","modified_gmt":"2020-03-03T13:14:41","slug":"kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase","title":{"rendered":"Come non spararsi nei piedi usando Liquibase","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Non \u00e8 mai successo, ed ecco di nuovo!<\/p>\n<p><\/p>\n<p>In un progetto recente, abbiamo deciso di utilizzare Liquibase sin dall'inizio per evitare problemi in futuro. Come si \u00e8 rivelato, non tutti i membri pi\u00f9 giovani del team sanno usarlo correttamente. Ho condotto un workshop interno che ho poi deciso di trasformare in un articolo. <\/p>\n<p><\/p>\n<p>L'articolo include consigli utili e una descrizione delle tre trappole pi\u00f9 evidenti in cui ci si pu\u00f2 imbattere lavorando con strumenti di migrazione dei database relazionali, in particolare Liquibase. \u00c8 destinato a programmatori Java di livello Junior e Middle, mentre per programmatori pi\u00f9 esperti potrebbe essere interessante per strutturare e ripassare ci\u00f2 che probabilmente \u00e8 gi\u00e0 noto. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Come non spararsi nei piedi usando Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/f8b3c9a456bde7aa123702fae132b4b8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Liquibase e Flyway sono le principali tecnologie concorrenti per la gestione delle versioni delle strutture relazionali nel mondo Java. Il primo \u00e8 completamente gratuito e, nella pratica, \u00e8 spesso scelto per l'uso, quindi Liquibase \u00e8 stato scelto come protagonista della pubblicazione. Tuttavia, alcune delle pratiche descritte possono essere universali, a seconda dell'architettura della vostra applicazione. <\/p>\n<p><\/p>\n<p>Le migrazioni delle strutture relazionali sono un metodo nato per affrontare la scarsa flessibilit\u00e0 dei dati relazionali. Nell'era della moda per la programmazione orientata agli oggetti, il modo di lavorare con i database implicava che descrivessimo una volta per tutte lo schema e non lo tocchiamo pi\u00f9. Ma la realt\u00e0 \u00e8 che tutto cambia, e le modifiche nella struttura delle tabelle sono abbastanza frequenti. Naturalmente, il processo stesso pu\u00f2 essere doloroso e sgradevole. <\/p>\n<p><\/p>\n<p>Non scender\u00f2 nei dettagli della tecnologia e delle istruzioni per aggiungere la libreria al proprio progetto, su questo argomento sono stati scritti abbastanza articoli:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/460377\/\">Uso di Liquibase per gestire la struttura del database in un'applicazione Spring Boot. Parte 1<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/460907\/\">Uso di Liquibase per gestire la struttura del database in un'applicazione Spring Boot. Parte 2<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/436994\/\">Liquibase e Maven<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/330662\/\">Approcci alla versioning delle modifiche del database<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/271719\/\">Spring MVC\/Security, REST, Hibernate, Liquibase avviato in due righe<\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<p>Inoltre, c'era gi\u00e0 un ottimo articolo sui consigli utili:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/179425\/\">Uso di Liquibase senza problemi. 10 consigli dall'esperienza reale.<\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"sovety\">Consigli<\/h2>\n<p><\/p>\n<p>Voglio condividere i miei consigli e commenti, che sono nati attraverso sudore, sangue e dolori nella risoluzione dei problemi di migrazione.<\/p>\n<p><\/p>\n<h3 id=\"1--pered-rabotoy-sleduet-oznakomitsya-s-razdelom-luchshih-praktik-na-saytehttpswwwliquibaseorgbestpracticeshtml-liquibase\">1. Prima di iniziare, dovresti familiarizzare con la sezione delle migliori pratiche su <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/bestpractices.html\">sito<\/a><\/noindex> Liquibase<\/h3>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/bestpractices.html\">L\u00ec<\/a><\/noindex> Sono descritte cose semplici, ma molto importanti, senza le quali l'uso della libreria pu\u00f2 complicarvi la vita. Ad esempio, un approccio non strutturato alla gestione dei changset porter\u00e0 prima o poi a confusione e migrazioni rotte. Se si distribuiscono modifiche alla struttura del database e alla logica dei servizi che dipendono l'una dall'altra in momenti diversi, c'\u00e8 una grande probabilit\u00e0 che questo porti a test falliti o a un ambiente non funzionante. Inoltre, le raccomandazioni su come utilizzare Liquibase sul sito ufficiale contengono un punto riguardo alla scrittura e verifica degli script di rollback insieme agli script di migrazione principali. E nell'articolo <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/178665\/\">https:\/\/habr.com\/ru\/post\/178665\/<\/a><\/noindex> ci sono esempi di codice riguardanti le migrazioni e il meccanismo di rollback. <\/p>\n<p><\/p>\n<h3 id=\"2-esli-nachali-ispolzovat-sredstva-migracii--ne-dopuskayte-manualnyh-ispravleniy-v-strukture-bazy\">2. Se inizi a usare strumenti di migrazione, non permettere modifiche manuali nella struttura del database.<\/h3>\n<p><\/p>\n<p>Come si suol dire: \u00abUna volta Persil, sempre Persil\u00bb. Se il database della tua applicazione \u00e8 iniziato a essere gestito tramite Liquibase, ogni modifica manuale porta immediatamente a uno stato inconsistente, e il livello di fiducia nei changset diventa zero. I rischi potenziali sono diverse ore spese per ripristinare il database, nella peggiore delle ipotesi, un server perso. Se nella tua squadra c'\u00e8 un DBA architect \"di vecchio stampo\", spiega pazientemente e attentamente come andr\u00e0 male se decide di modificare il database a suo piacimento da un presunto SQL Developer. <\/p>\n<p><\/p>\n<h3 id=\"3-esli-chendzhset-uzhe-byl-zapushen-v-repozitoriy-izbegayte-redaktirovaniya\">3. Se un changset \u00e8 gi\u00e0 stato pushato nel repository, evita di modificare.<\/h3>\n<p><\/p>\n<p>Se un altro sviluppatore ha fatto pull e ha applicato un changset che sar\u00e0 successivamente modificato, sicuramente parler\u00e0 bene di te quando ricever\u00e0 un errore all'avvio dell'applicazione. Se la modifica di un changset dovesse in qualche modo trapelare nel dev, dovrai seguire una difficile strada di hotfix. Il nocciolo del problema riguarda la validazione delle modifiche tramite hash \u2013 il meccanismo principale di Liquibase. Quando si modifica il codice di un changset, cambia anche l'hash. La modifica dei changset \u00e8 possibile solo se esiste la possibilit\u00e0 di ripristinare l'intero database da zero senza perdita di dati. In tal caso, il refactoring del codice SQL o XML pu\u00f2, al contrario, semplificare la vita e rendere le migrazioni pi\u00f9 leggibili. Un esempio potrebbe essere la situazione in cui, all'inizio dell'applicazione, lo schema del database originale \u00e8 stato concordato all'interno del team. <\/p>\n<p><\/p>\n<h3 id=\"4--imey-proverennye-bekapy-baz-dannyh-esli-eto-vozmozhno\">4. Avere backup verificati del database, se possibile<\/h3>\n<p><\/p>\n<p>Qui, penso sia chiaro. Nel caso in cui la migrazione non vada a buon fine, tutto pu\u00f2 essere ripristinato. In Liquibase c'\u00e8 uno strumento di rollback, ma gli script per il rollback vengono scritti dallo sviluppatore stesso, e potrebbero esserci problemi con la stessa probabilit\u00e0 degli script del changelog principale. Questo significa che \u00e8 utile prendere precauzioni con i backup in ogni caso. <\/p>\n<p><\/p>\n<h3 id=\"5-ispolzuy-proverennye-bekapy-baz-dannyh-v-razrabotke-esli-eto-vozmozhno\">5. Utilizza backup del database verificati nello sviluppo, se possibile<\/h3>\n<p><\/p>\n<p>Se ci\u00f2 non contraddice i contratti e la privacy, il database non contiene dati personali e non pesa come due soli \u2014 prima di applicare la migrazione sui server live, \u00e8 possibile testare come funziona sulla macchina dello sviluppatore e identificare quasi il 100% dei potenziali problemi durante la migrazione. <\/p>\n<p><\/p>\n<h3 id=\"6-obschaysya-s-drugimi-razrabotchikami-v-komande\">6. Comunica con gli altri sviluppatori del team<\/h3>\n<p><\/p>\n<p>In un processo di sviluppo ben organizzato, tutti nel team sanno chi sta lavorando a cosa. Nella realt\u00e0 spesso non \u00e8 cos\u00ec, quindi, se stai preparando modifiche alla struttura del database nel contesto del tuo compito, \u00e8 consigliabile informare ulteriormente l'intero team. Se qualcuno sta facendo modifiche in parallelo, dovresti organizzarti con attenzione. \u00c8 utile comunicare con i colleghi anche al termine del lavoro, non solo all'inizio. Molti problemi potenziali con i changelog possono essere risolti nella fase di code review. <\/p>\n<p><\/p>\n<h3 id=\"7-dumay-chto-delaesh\">7. Pensa a quello che fai!<\/h3>\n<p><\/p>\n<p>Sembrerebbe un consiglio ovvio, applicabile a qualsiasi situazione. Tuttavia, molti problemi potrebbero essere evitati se lo sviluppatore analizzasse ancora una volta cosa sta facendo e quali potrebbero essere le conseguenze. Lavorare con le migrazioni richiede sempre maggiore attenzione e precisione. <\/p>\n<p><\/p>\n<h2 id=\"lovushki\">Trappole<\/h2>\n<p><\/p>\n<p>Ora esaminiamo alcune trappole comuni in cui \u00e8 possibile cadere se non si seguono i consigli sopra, e cosa fare realmente?<\/p>\n<p><\/p>\n<h3 id=\"situaciya-1-dva-razrabotchika-pytayutsya-odnovremenno-dobavlyat-novye-chendzhsety\">Situazione 1. Due sviluppatori cercano di aggiungere nuovi changelog contemporaneamente<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Come non spararsi nei piedi usando Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/20706fc970510bc06634fa001a4c7ceb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nVasia e Petja vogliono creare un changelog della versione 4, senza sapere l'uno dell'altro. Hanno effettuato modifiche nella struttura del database e hanno presentato una pull request, con file changelog diversi. Di seguito \u00e8 proposto il seguente meccanismo di azione:<\/p>\n<p><\/p>\n<h4 id=\"kak-reshat\">Come risolvere<\/h4>\n<p><\/p>\n<ol>\n<li>In qualche modo, i colleghi devono concordare in quale ordine devono andare i loro changelog, ad esempio, quello di Petja deve essere applicato per primo. <\/li>\n<li>Qualcuno deve integrare il secondo e contrassegnare il changeSet di Vasia con la versione 5. Questo pu\u00f2 essere fatto tramite Cherry Pick o una fusione accurata. <\/li>\n<li>Dopo le modifiche, \u00e8 fondamentale verificare la validit\u00e0 delle azioni effettuate.<br \/>\nIn realt\u00e0, i meccanismi di Liquibase consentiranno di avere nel repository due changeSet della versione 4, quindi puoi lasciare tutto com'\u00e8. In altre parole, avrai semplicemente due modifiche della versione 4 con nomi diversi. Con questo approccio, diventa molto difficile orientarsi successivamente nelle versioni del database. <\/li>\n<\/ol>\n<p><\/p>\n<p>Inoltre, Liquibase, come la casa degli hobbit, custodisce molti segreti. Uno di questi \u00e8 la chiave validCheckSum, che \u00e8 apparsa dalla versione 1.7 e consente di specificare un valore di checksum valido per un determinato changeSet, indipendentemente da ci\u00f2 che \u00e8 memorizzato nel database. Documentazione <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/documentation\/changeset.html\">https:\/\/www.liquibase.org\/documentation\/changeset.html<\/a><\/noindex> afferma quanto segue:<\/p>\n<p><\/p>\n<blockquote><p>Add a checksum that is considered valid for this changeSet, regardless of what is stored in the database. Used primarily when you need to change a changeSet and don&#8217;t want errors thrown on databases on which it has already run (not a recommended procedure)<\/p><\/blockquote>\n<p>S\u00ec, questa procedura non \u00e8 raccomandata. Ma a volte un potente mago luminoso padroneggia anche tecniche oscure. <\/p>\n<p><\/p>\n<h3 id=\"situaciya-2-migraciya-kotoraya-zavisit-ot-dannyh\">Situazione 2. Migrazione che dipende dai dati<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Come non spararsi nei piedi usando Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/31a6eebb55278c0631115bf16483c7b8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Supponiamo che non hai la possibilit\u00e0 di utilizzare backup database dai server attivi. Petya ha creato un changeSet, l'ha testato localmente e con piena fiducia nella sua correttezza ha effettuato una pull request in sviluppo. Il leader del progetto ha verificato, ha chiesto se Petya lo avesse controllato, e successivamente ha fuso. Ma il deployment sul server di sviluppo \u00e8 fallito.<\/p>\n<p><\/p>\n<p>In realt\u00e0, \u00e8 possibile, e nessuno \u00e8 al sicuro da ci\u00f2. Accade quando le modifiche alla struttura delle tabelle sono in qualche modo legate a dati specifici nel database. \u00c8 ovvio che se il database di Petya \u00e8 riempito solo con dati di test, potrebbe non coprire tutti i casi problematici. Ad esempio, durante la cancellazione di una tabella si scopre che ci sono record in altre tabelle tramite Foreign Key, collegati ai record nella tabella eliminata. Oppure, modificando il tipo di colonna, si scopre che non il 100% dei dati pu\u00f2 essere convertito al nuovo tipo. <\/p>\n<p><\/p>\n<h4 id=\"kak-reshat-1\">Come risolvere<\/h4>\n<p><\/p>\n<ul>\n<li>Scrivere script speciali che verranno applicati una sola volta insieme alla migrazione e porteranno i dati nel formato corretto. Questo \u00e8 un modo generale per risolvere il problema del trasferimento dei dati nelle nuove strutture dopo aver applicato le migrazioni, ma qualcosa di simile pu\u00f2 essere applicato anche prima, in casi specifici. Questo approccio, ovviamente, non \u00e8 sempre disponibile, poich\u00e9 modificare i dati sui server attivi pu\u00f2 essere pericoloso e persino dannoso. <\/li>\n<li>Un altro approccio complesso \u00e8 modificare il changset esistente. La difficolt\u00e0 sta nel fatto che tutte le DB, dove \u00e8 stato gi\u00e0 applicato nella sua forma attuale, dovranno essere ripristinati. \u00c8 del tutto possibile che l'intero team backend sar\u00e0 costretto a installare localmente il DB da zero. <\/li>\n<li>E il modo pi\u00f9 universale \u00e8 trasferire il problema dei dati nell'ambiente dello sviluppatore ricreando la stessa situazione e aggiungendo un nuovo changset, fino a quello rotto, che permetter\u00e0 di aggirare il problema.<br \/>\n<img decoding=\"async\" alt=\"Come non spararsi nei piedi usando Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/b5d28a940a7a35b6cd7a819a8e68f027.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ul>\n<p><\/p>\n<p>In generale, pi\u00f9 il database per composizione dei dati \u00e8 simile al database del server di produzione, minore sar\u00e0 la possibilit\u00e0 che i problemi con le migrazioni si verifichino ampiamente. E, naturalmente, prima di inviare il changset nel repository, vale la pena riflettere alcune volte se questo romper\u00e0 qualcosa. <\/p>\n<p><\/p>\n<h3 id=\"situaciya-3-liquibase-nachinaet-primenyatsya-uzhe-posle-vyhoda-v-prodakshn\">Situazione 3. Liquibase inizia ad essere applicato dopo l'uscita in produzione<\/h3>\n<p><\/p>\n<p>Supponiamo che il team leader abbia chiesto a Petya di integrare Liquibase nel progetto, tuttavia il progetto \u00e8 gi\u00e0 in produzione e c'\u00e8 gi\u00e0 una struttura del database esistente.<\/p>\n<p><\/p>\n<p>Di conseguenza, il problema consiste nel fatto che sui nuovi server o macchine degli sviluppatori, i dati delle tabelle devono essere ricreati da zero, mentre l'ambiente esistente deve rimanere in uno stato consistente, pronto per ricevere nuovi changset. <\/p>\n<p><\/p>\n<h4 id=\"kak-reshat-2\">Come risolvere<\/h4>\n<p><\/p>\n<p>Qui ci sono anche diversi percorsi:<\/p>\n<p><\/p>\n<ul>\n<li>Il primo e pi\u00f9 ovvio \u00e8 avere uno script separato che deve essere applicato manualmente all'inizializzazione di un nuovo ambiente. <\/li>\n<li>Il secondo, meno ovvio, \u00e8 avere una migrazione Liquibase che si trova in un altro Contesto Liquibase e applicarla. Maggiori dettagli sul Contesto Liquibase possono essere letti qui: <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/documentation\/contexts.html\">https:\/\/www.liquibase.org\/documentation\/contexts.html<\/a><\/noindex>. In generale, questo \u00e8 un meccanismo interessante che pu\u00f2 essere applicato con successo, ad esempio, per il testing. <\/li>\n<li>Il terzo percorso consiste in diversi passaggi. Innanzitutto deve essere creata una migrazione per le tabelle gi\u00e0 esistenti. Successivamente deve essere applicata in un certo ambiente e in questo modo si otterr\u00e0 il suo hash. Il passaggio successivo consiste nell'inizializzare nel nostro server non vuoto tabelle Liquibase vuote e nella tabella con la storia di applicazione dei cambiamenti si pu\u00f2 inserire manualmente una registrazione di un cambiamento \"applicato\" con le modifiche gi\u00e0 presenti nel database. In questo modo, nella storia del server esistente si partir\u00e0 dalla versione 2 e tutti i nuovi ambienti si comporteranno in modo identico.<br \/>\n<img decoding=\"async\" alt=\"Come non spararsi nei piedi usando Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/78881ee56a6ee3ba4e0cd1089598c3c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"situaciya-4-migracii-stanovyatsya-ogromnymi-i-ne-uspevayut-vypolnyatsya\">Situazione 4. Le migrazioni diventano enormi e non riescono a essere completate.<\/h3>\n<p><\/p>\n<p>All'inizio dello sviluppo del servizio, di solito, Liquibase viene utilizzato come dipendenza esterna e tutte le migrazioni vengono elaborate all'avvio dell'applicazione. Tuttavia, col tempo, \u00e8 possibile imbattersi nei seguenti casi:<\/p>\n<p><\/p>\n<ul>\n<li>Le migrazioni diventano enormi e richiedono molto tempo per essere eseguite.<\/li>\n<li>Sorge la necessit\u00e0 di migrazioni in ambienti distribuiti, ad esempio su pi\u00f9 istanze di server DB contemporaneamente.<br \/>\nIn tal caso, l'applicazione delle migrazioni richiede troppo tempo, portando a un timeout all'avvio dell'applicazione. Inoltre, applicare le migrazioni per ogni istanza dell'applicazione separatamente potrebbe portare a una desincronizzazione tra i diversi server. <\/li>\n<\/ul>\n<p><\/p>\n<h4 id=\"kak-reshat-3\">Come risolvere<\/h4>\n<p><\/p>\n<p>In questi casi, il tuo progetto \u00e8 gi\u00e0 grande, forse anche maturo, e Liquibase inizia a fungere da strumento esterno separato. Infatti, Liquibase come libreria viene assemblata in un file jar e pu\u00f2 funzionare sia come dipendenza all'interno di un progetto sia in modo autonomo. <\/p>\n<p><\/p>\n<p>In modalit\u00e0 autonoma, puoi delegare l'applicazione delle migrazioni al tuo ambiente CI\/CD o sulle spalle forti dei tuoi amministratori di sistema o specialisti del deployment. Per questo sar\u00e0 necessaria la linea di comando di Liquibase. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/documentation\/command_line.html\">https:\/\/www.liquibase.org\/documentation\/command_line.html<\/a><\/noindex>. In questa modalit\u00e0 diventa possibile avviare l'applicazione solo dopo che tutte le migrazioni necessarie sono state completate.<\/p>\n<p><\/p>\n<h2 id=\"vyvod\">Conclusione<\/h2>\n<p><\/p>\n<p>In realt\u00e0, ci sono molte pi\u00f9 insidie nella gestione delle migrazioni del database, e molte di esse richiedono un approccio creativo. \u00c8 importante capire che, se utilizzato correttamente, questo strumento permette di evitare la maggior parte di queste insidie. Personalmente, mi sono trovato a dover affrontare tutti i problemi menzionati in vari modi, e alcuni di essi sono stati il risultato dei miei errori. Questo accade generalmente per distrazione, ma a volte anche a causa di una incompetenza tecnica nell'uso dello strumento.<\/p>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/epam_systems\/blog\/489198\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0438 \u0432\u043e\u0442 \u043e\u043f\u044f\u0442\u044c! \u041d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Liquibase \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c. \u041a\u0430\u043a \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u043d\u0435 \u0432\u0441\u0435 \u043c\u043e\u043b\u043e\u0434\u044b\u0435 \u0447\u043b\u0435\u043d\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0443\u043c\u0435\u044e\u0442 \u0435\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u042f \u043f\u0440\u043e\u0432\u0451\u043b \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0432\u043e\u0440\u043a\u0448\u043e\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0442\u0435\u043c \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u044e. \u0421\u0442\u0430\u0442\u044c\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u043e\u0432\u0435\u0442\u044b \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0440\u0435\u0445 \u0441\u0430\u043c\u044b\u0445 \u044f\u0432\u043d\u044b\u0445 \u043b\u043e\u0432\u0443\u0448\u0435\u043a, \u0432 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":70974,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-70973","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0438 \u0432\u043e\u0442 \u043e\u043f\u044f\u0442\u044c! \u041d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Liquibase \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a \u043d\u0435 \u0432\u044b\u0441\u0442\u0440\u0435\u043b\u0438\u0442\u044c \u0441\u0435\u0431\u0435 \u0432 \u043d\u043e\u0433\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Liquibase | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0438 \u0432\u043e\u0442 \u043e\u043f\u044f\u0442\u044c! \u041d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Liquibase \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-02-22T21:58:26+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-03T13:14:41+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Come non spararsi sui piedi utilizzando Liquibase | ProHoster","description":"Non \u00e8 mai successo prima, eppure eccone un altro! In un progetto recente abbiamo deciso di utilizzare Liquibase fin dall'inizio, per evitare problemi in futuro.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a \u043d\u0435 \u0432\u044b\u0441\u0442\u0440\u0435\u043b\u0438\u0442\u044c \u0441\u0435\u0431\u0435 \u0432 \u043d\u043e\u0433\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Liquibase | ProHoster","og:description":"\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0438 \u0432\u043e\u0442 \u043e\u043f\u044f\u0442\u044c! \u041d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Liquibase \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c.","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-02-22T21:58:26+00:00","article:modified_time":"2020-03-03T13:14:41+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"70973","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 19:10:24","updated":"2022-09-28 08:39:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/70973","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=70973"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/70973\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/70974"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=70973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=70973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=70973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}