⬆️ ⬇️

Using Liquibase without a headache. 10 tips from real development experience

kdpv Liquibase is a database migration management system. This is the second article about Liquibase, this time containing tips on “combat” use of the system. For getting the basic information, the first article-translation “Managing DB Migrations with Liquibase” ( link ) is suitable.



Like many tools that make life easier for software developers, Liquibase has a “reverse side of the coin” that you have to face sooner or later.



Here are 10 things that at a certain point when working with Liquibase was a discovery for me.

')

1. Versioning of the application should be reflected in the folder structure of migrations



If you do not follow this rule, the changelog files will quickly decorate the migration folder with its number and unusual names.

At the moment, for myself, I have developed an optimal strategy for naming files and folders. Here she is:



/db-migrations /v-1.0 /2013-03-02--01-initial-schema-import.xml /2013-03-02--02-core-data.xml /2013-03-04--01-notifications.xml /changelog-v.1.0-cumulative.xml /v-2.0 ... /changelog-v.2.0-cumulative.xml /changelog.xml 


More details:



1.1. Changes to database changes should be contained in separate folders and correspond to the application versions.


Pros:





1.2. Have a cumulative changelog file for each version.


The main migration file is /db-migrations/changelog.xml. Only the cumulative changelog files of each version are included in it (“include” tag).



 <?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"> <!-- Should be only links to per-version cumulative changelog files. --> <include file="v-1.0/changelog-v.1.0-cumulative.xml" relativeToChangelogFile="true"/> <include file="v-2.0/changelog-v.2.0-cumulative.xml" relativeToChangelogFile="true"/> </databaseChangeLog> 


In turn, the cumulative changers of application versions include specific changeset files.

Thus, it is possible not to litter the main file of changelogs.



1.3. Follow file naming conventions


The file naming rule makes it possible to understand what followed what without viewing cumulative file changer files.



 -<DATE_INCR>-.xml 
    

DATE

DATE_INCR – ( .)

DESCR – .

:

2013-03-02--01-initial-schema-import.xml



2. ,

( rollback ) .

, . , .



, PROD-, , , , .



3. ,

— . , , .

, , rollback. .



4. , ,

, Oracle MySQL DDL- .

, , DDL-, .

( ):



<changeSet id="2013-03-02-initial-schema-import-1" author="eg"> <createTable tableName="HOUSES"> <column name="ID" type="BIGINT" /> </createTable> <addPrimaryKey tableName="HOUSES" columnNames="ID" /> </changeSet>

-<DATE_INCR>-.xml

DATE

DATE_INCR – ( .)

DESCR – .

:

2013-03-02--01-initial-schema-import.xml



2. ,

( rollback ) .

, . , .



, PROD-, , , , .



3. ,

— . , , .

, , rollback. .



4. , ,

, Oracle MySQL DDL- .

, , DDL-, .

( ):



<changeSet id="2013-03-02-initial-schema-import-1" author="eg"> <createTable tableName="HOUSES"> <column name="ID" type="BIGINT" /> </createTable> <addPrimaryKey tableName="HOUSES" columnNames="ID" /> </changeSet>

-<DATE_INCR>-.xml

DATE

DATE_INCR – ( .)

DESCR – .

:

2013-03-02--01-initial-schema-import.xml



2. ,

( rollback ) .

, . , .



, PROD-, , , , .



3. ,

— . , , .

, , rollback. .



4. , ,

, Oracle MySQL DDL- .

, , DDL-, .

( ):



<changeSet id="2013-03-02-initial-schema-import-1" author="eg"> <createTable tableName="HOUSES"> <column name="ID" type="BIGINT" /> </createTable> <addPrimaryKey tableName="HOUSES" columnNames="ID" /> </changeSet>

-<DATE_INCR>-.xml

DATE

DATE_INCR – ( .)

DESCR – .

:

2013-03-02--01-initial-schema-import.xml



2. ,

( rollback ) .

, . , .



, PROD-, , , , .



3. ,

— . , , .

, , rollback. .



4. , ,

, Oracle MySQL DDL- .

, , DDL-, .

( ):



<changeSet id="2013-03-02-initial-schema-import-1" author="eg"> <createTable tableName="HOUSES"> <column name="ID" type="BIGINT" /> </createTable> <addPrimaryKey tableName="HOUSES" columnNames="ID" /> </changeSet>

-<DATE_INCR>-.xml

DATE

DATE_INCR – ( .)

DESCR – .

:

2013-03-02--01-initial-schema-import.xml



2. ,

( rollback ) .

, . , .



, PROD-, , , , .



3. ,

— . , , .

, , rollback. .



4. , ,

, Oracle MySQL DDL- .

, , DDL-, .

( ):



<changeSet id="2013-03-02-initial-schema-import-1" author="eg"> <createTable tableName="HOUSES"> <column name="ID" type="BIGINT" /> </createTable> <addPrimaryKey tableName="HOUSES" columnNames="ID" /> </changeSet>

-<DATE_INCR>-.xml

DATE

DATE_INCR – ( .)

DESCR – .

:

2013-03-02--01-initial-schema-import.xml



2. ,

( rollback ) .

, . , .



, PROD-, , , , .



3. ,

— . , , .

, , rollback. .



4. , ,

, Oracle MySQL DDL- .

, , DDL-, .

( ):



<changeSet id="2013-03-02-initial-schema-import-1" author="eg"> <createTable tableName="HOUSES"> <column name="ID" type="BIGINT" /> </createTable> <addPrimaryKey tableName="HOUSES" columnNames="ID" /> </changeSet>

-<DATE_INCR>-.xml

DATE

DATE_INCR – ( .)

DESCR – .

:

2013-03-02--01-initial-schema-import.xml



2. ,

( rollback ) .

, . , .



, PROD-, , , , .



3. ,

— . , , .

, , rollback. .



4. , ,

, Oracle MySQL DDL- .

, , DDL-, .

( ):



<changeSet id="2013-03-02-initial-schema-import-1" author="eg"> <createTable tableName="HOUSES"> <column name="ID" type="BIGINT" /> </createTable> <addPrimaryKey tableName="HOUSES" columnNames="ID" /> </changeSet>


If an error occurs while adding an index, the HOUSES table will not be deleted!

How to avoid pain? Every change to the database schema must live in its changelog.



Example (so correct):



 <changeSet id="2013-03-02-initial-schema-import-1" author="eg"> <createTable tableName="HOUSES"> <column name="ID" type="BIGINT" /> </createTable> </changeSet> <changeSet id="2013-03-02-initial-schema-import-2" author="eg"> <addPrimaryKey tableName="HOUSES" columnNames="ID" /> </changeSet> 




5. Path run migration script is set to



Look at the two commands to start the database schema migration script



 cd c:/mychangelogs/ liquibase --url=jdbc:mysql://localhost:3306/liquiblog --driver=com.mysql.jdbc.Driver --username=root --password="" --changeLogFile=db.changelog-0.1.0.xml update 


 liquibase --url=jdbc:mysql://localhost:3306/liquiblog --driver=com.mysql.jdbc.Driver --username=root --password="" --changeLogFile=c:/mychangelogs/db.changelog-0.1.0.xml update 


It seems that the second team should not roll any changes. But this is not the case; Liquibase stores the path to the changelog file in the FILENAME column of the DATABASECHANGELOG table.

In connection with this fact, at the second launch Liquibase will consider all changesets as new. This can break your data schema!



How to avoid pain? Always run changers using relative paths from the same directory.



6. Precondition conditions do not affect the changelog checksum.



This is good news for those who like to make mistakes (that is, all of us, sooner or later). Sometimes this allows you to change the conditions of the changeset application, thus “correcting the past”.



7. Liquibase is not so good for frequently changing data.



Once we tried to migrate many of the same type, but changing from version to version of the configuration data via changelogs. It turned out to be very sad - constantly someone from the team was wrong, the error was leaving for the test environment, it was necessary to roll back completely manually (remember the checksum of changesets?).

The sad picture had to be corrected by a sober approach to the specific situation. Liquibase was left to change the data schema, and the configuration data with each version was poured by a Groovy script, having the properties file as the source.



8. Do not trust scripts for automatic generation of changesets.



Liquibase can generate



These amenities should be treated with caution. This is just a little rid of the routine, no more. All changesets must be viewed, understood and verified. You do not want to correct the logical error (foiled by the stupid utility) who went to PROD, right?



9. Use XML, not DSL



Sometimes you want to “make life easier” and abandon XML by starting to use shorter DSL (groovy, yaml, json)

All this is very good as long as you do not want to have:



So why refuse such useful things in favor of brevity? Apparently, I'm not so good a programmer to give up autocompletion for the sake of a little better readability of the code.



10. Study someone else's experience.



Although I learned most of the points in this article from my own experience, the official guide on the best practices of using Liquibase improves the perception of the tool ( link )



Successful migrations!

Source: https://habr.com/ru/post/179425/



All Articles