Liquibase is an open source database schema change management solution. What it means is that it will allow you to save as code in a version control tools changes to your database. It has capabilities to run and test database schema changes, to reduce errors, and you can deploy and roll back your database to any specific version.
Even though it is an open source solution, it does have paid “Pro” solution with support.
How it works
This is meant to be a brief introduction to present the tool, find more tailored information by joining the liquibase community.
Liquibase uses changeset which contains the information regarding the change to the database.
Historically they have been written in xml
but since, some other more user-friendly formats are available (YAML, JSON).
Here is an example of an XML change set to create the department
table with a few columns:
<changeSet id="1" author="liquibase">
<createTable tableName="department">
<column name="id" type="int">
<constraints primaryKey="true"/>
</column>
<column name="dept" type="varchar(${dep.size})">
<constraints nullable="false"/>
</column>
<column name="emp_id" type="int">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
Each change set should have a unique id and an author for traceability of the change, they are stored, so you can audit your system. The change sets are stored within changelogs, like a ledger of all the changes made by liquibase on the database.
Liquibase keep tracks of which change set have been applied in a tracking table directly in the database called
DATABASECHANGELOG
. It is created automatically by liquibase.
Changelog
To generate a changelog file in order to add a change set, use the liquibase cli, you can install it via brew or directly from the website, then run:
liquibase init project
This will initiate the liquibase project, so you can run other commands. You can modify the settings to connect to a
test database as well. You can update the liquibase.properties
file for that afterward.
You can create a xml changelog from this template or use the command line to generate one:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd"
logicalFilePath="db.changelog-577.xml">
</databaseChangeLog>
Inside should be all of your change sets.
Changeset
Here are some changeset that you can apply to your database. Those are examples
Grant rights to a user
This change doesn’t have a custom liquibase tag to it (unlike createTable
from the previous example). So in order
to make it work and grant some rights to your user, you will need to use the sql
change type which lets you enter
any SQL syntax:
<changeSet id="2" author="example" dbms="mysql" failOnError="false">
<preConditions onFail="CONTINUE" onError="CONTINUE" onSqlOutput="TEST">
<sqlCheck expectedResult="1">
SELECT COUNT(1) FROM information_schema.schemata WHERE schema_name = 'user'
</sqlCheck>
</preConditions>
<sql>
GRANT SELECT, INSERT, UPDATE, DELETE ON department TO user;
</sql>
</changeSet>
Here we are checking that the user user
exist on the database before granting new access to the department
table that
we created.
The dbms specify that we are applying this change to a mySQL database.
Create index
Indexes are used to allow MySQL to find rows with specific columns values quickly. With an index, instead of looking at all the data from the first row, the relevant information can be determined by only looking at the column information. The larger the table the more gain you will get by adding an index.
<changeSet id="3" author="example" dbms="mysql">
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<not>
<indexExists tableName="department" indexName="id_index"></indexExists>
</not>
</preConditions>
<createIndex tableName="department" indexName="id_index">
<column name="id"/>
</createIndex>
</changeSet>
Here we are adding an index called id_index
to the department
for the id
column. Note the pre-condition, if the
index already exist, we don’t re-create it.
Index creation can be costly in terms of time and resources.
Adding a column
Another typical example would be to add a column to an existing table, there’s a liquibase command for that:
<changeSet id="4" author="example">
<addColumn tableName="department">
<column name="name" type="varchar(32)" defaultValue="none">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>
Here we are adding a column on the department
table named name
which will have none
as the default value, but
can be nullable. It’s supposed to be a text hence the varchar(32)
.
With Liquibase commands
All of those changes are concerning an SQL, or MySQL database, which is what Liquibase is known for. However, there are some extension for NoSQL databases like MongoDb, but they use a different set of change type. (Because creating a table in MongoDb is nonsense, you would need createCollection instead).
However, the command should stay the same. To apply changes, once your ChangeSet in the ChangeLog, use this command to update your database:
liquibase update
Assuming everything is properly set up, you should be able to see the changes reflected in your database. For more help on the commands, check out the docs.