Learn the main concepts that describe the execution model of Liquibase.
Liquibase manages the execution of database changes.
A change can be a simple statement written in a dialect understood by the target database.
This is for instance the case of the "SQL" change (aliased to Cypher
A change can also be a complex transformation operation, such as "Rename Table".
The interest of complex changes is two-fold:
- they encapsulate several basic operations, which would otherwise be tedious and error-prone to write
- most of these complex changes are portable across different database management systems
In the case of
liquibase-neo4j, portability is not a concern.
liquibase-neo4j only supports Neo4j. There is
currently no plan to support other graph databases.
This may change when the upcoming GQL standard matures and the ecosystem fully embraces it.
Change Sets and Transactions#
Changes are grouped into change sets.
Changes of a single change set are run in a single transaction by default. Either all the changes succeed or they all fail.
Neo4j schema operations and data operations cannot be part of the same transaction. They are better defined in different change sets.
You can disable this behavior by setting the change set
runInTransaction attribute to
In that case, each change of the change set runs in its own auto-commit transaction.
Learn more about the best practice around the
Change Logs and Consistency#
Change sets are defined in change logs, usually stored as flat files on the local file system.
A change log may include other change logs and/or define change sets.
Change log files can be written in different formats. Formats can even be mixed (for instance: a top-level XML change log can include a SQL change log).
Change sets are uniquely identified by an ID and an author name, as well as the change log path that defines it. This prevents unintended collisions.
The Liquibase runtime requires a single change log entry point. It will resolve all change log inclusions to a linear sequence of change sets.
Change sets may depend on each other. For instance, a previous change set may define a table and the next one assumes the table exists and inserts seed data into it.
In the case of Neo4j, a bookmark mechanism fulfills that property. A bookmark is passed along a transaction and identifies a state that the targeted instance needs to reach before processing that transaction.
Based upon this idea, native Neo4j drivers define sessions. Sessions are bound to a single thread of execution and automatically chains the bookmarks of a previous successful transaction to the next one.
The JDBC connector used by
liquibase-neo4j relies on the native Java driver and ties a single JDBC connection to a single
Neo4j session. A single Liquibase invocation results in a single connection to be open.
As a consequence, the causal consistency property is automatically ensured.
Persistence and History Graph#
Liquibase is by default an append-only change executor. Indeed, instead of altering existing change sets, the most common approach is to append new change sets to the existing sequence.
Altering change sets is prohibited by default. Change sets are immutable.
In order to make them mutable, the change set needs to set its attribute
Liquibase does not re-run change sets by default. Once they are executed against a target database, they are not run again.
In order to re-run change sets, their attribute
runAlways needs to be set to
The executed change sets need to be persisted.
liquibase-neo4j stores them as a history graph (the RDBMS equivalent is the
liquibase-neo4j stores this history graph in the same database (tenant) as the one the change log runs against.
Executing a change log against one database and persisting the history in another is not supported.
liquibase-neo4j makes no guarantee that the history graph schema remains unchanged from version to version, even
during a non-major version upgrade.
Users are not expected to manipulate the history graph directly.
If the schema changes,
liquibase-neo4j will automatically run internal migrations against the history graph
persisted by a former version.
liquibase-neo4j must not be executed concurrently against the same server and database.
Similar to the
liquibase-neo4j attempts to store a unique
__LiquibaseLock node. If this fails, this means another execution is going on and the execution stops.