Liquibase Percona Extension

Build Status

Extension to support the tool pt-online-schema-change from Percona Toolkit. This extension replaces a couple of the default changes to use pt-online-schema-change instead of SQL. This allows to perform a non-locking database upgrade.

Table Of Contents

Supported Databases

MySQL is the only supported database. The extension checks whether it is being run against a MySQL database. If not, it falls back to the default changes provided by liquibase-core.

Liquibase version(s) tested against

Supported Changes and examples

The following changes are supported:

AddColumn

Since: liquibase-percona 1.0.0

Automatic rollback supported? yes

Example:

<changeSet id="2" author="Alice">
    <addColumn tableName="person">
        <column name="address" type="varchar(255)"/>
    </addColumn>
</changeSet>

Corresponding command:

pt-online-schema-change --alter="ADD COLUMN address VARCHAR(255)" ...

AddForeignKeyConstraint

Since: liquibase-percona 1.3.0

Automatic rollback supported? yes

Example:

<changeSet id="3" author="Alice">
    <addForeignKeyConstraint constraintName="fk_person_address"
        referencedTableName="person" referencedColumnNames="id"
        baseTableName="address" baseColumnNames="person_id"/>
</changeSet>

Corresponding command:

pt-online-schema-change --alter="ADD CONSTRAINT fk_person_address FOREIGN KEY (person_id) REFERENCES person (id)" ...

AddUniqueConstraint

Since: liquibase-percona 1.3.0

Automatic rollback supported? yes

Example:

<changeSet id="2" author="Alice">
    <addUniqueConstraint columnNames="id, name" tableName="person" constraintName="uq_id_name"/>
</changeSet>

Corresponding command:

pt-online-schema-change --alter="ADD CONSTRAINT uq_id_name UNIQUE (id, name)" ...

Note: pt-online-schema-change is executed with the option --nocheck-unique-key-change. This enables to add a unique index, but can cause data loss, since duplicated rows are ignored. See Percona Toolkit Documentation for more information.

CreateIndex

Since: liquibase-percona 1.2.0

Automatic rollback supported? yes

Example:

<changeSet id="2" author="Alice">
    <createIndex indexName="emailIdx" tableName="person" unique="true">
        <column name="email"/>
    </createIndex>
</changeSet>

Corresponding command:

pt-online-schema-change --alter="ADD UNIQUE INDEX emailIdx (email)" ...

Note: pt-online-schema-change is executed with the option --nocheck-unique-key-change. This enables to add a unique index, but can cause data loss, since duplicated rows are ignored. See Percona Toolkit Documentation for more information.

DropColumn

Since: liquibase-percona 1.0.0

Automatic rollback supported? no

Example:

<changeSet id="2" author="Alice">
    <dropColumn tableName="person" columnName="age"/>
</changeSet>

Corresponding command:

pt-online-schema-change --alter="DROP COLUMN age" ...

DropForeignKeyConstraint

Since: liquibase-percona 1.3.0

Automatic rollback supported? no

Example:

<changeSet id="4" author="Alice">
    <dropForeignKeyConstraint baseTableName="address" constraintName="fk_person_address" />
</changeSet>

Corresponding command:

pt-online-schema-change --alter="DROP FOREIGN KEY _fk_person_address" ...

DropUniqueConstraint

Since: liquibase-percona 1.3.0

Automatic rollback supported? no

Example:

<changeSet id="3" author="Alice">
    <dropUniqueConstraint tableName="person" constraintName="uq_id_name"/>
</changeSet>

Corresponding command:

pt-online-schema-change --alter="DROP KEY uq_id_name" ...

DropIndex

Since: liquibase-percona 1.2.0

Automatic rollback supported? no

Example:

<changeSet id="3" author="Alice">
    <dropIndex indexName="emailIdx" tableName="person"/>
</changeSet>

Corresponding command:

pt-online-schema-change --alter="DROP INDEX emailIdx" ...

ModifyDataType

Since: liquibase-percona 1.2.0

Automatic rollback supported? no

Example:

<changeSet id="2" author="Alice">
    <modifyDataType tableName="person" columnName="email" newDataType="VARCHAR(400)"/>
</changeSet>

Corresponding command:

pt-online-schema-change --alter="MODIFY email VARCHAR(400)" ...

Configuration

UsePercona flag

Each change allows to enable or disable the usage of percona toolkit via the property usePercona. By default, the percona toolkit is used, see also the system property liquibase.percona.defaultOn.

Example:

- changeSet:
    id: 2
    author: Alice
    changes:
      - addColumn:
          tableName: person
          usePercona: false
          columns:
            - column:
                name: address
                type: varchar(255)

This flag exists since liquibase-percona 1.3.0

It is supported by using the YAML format and since liquibase 3.6.0, you can use it in XML changesets, too:

<addColumn tableName="person" xmlns:liquibasePercona="http://github.com/adangel/liquibase-percona" liquibasePercona:usePercona="false">
    <column name="address" type="varchar(255)"/>
</addColumn>

System Properties

The extension supports the following java system properties:

You can set these properties by using the standard java -D option:

java -Dliquibase.percona.skipChanges=createIndex,dropColumn -jar liquibase.jar ...

Note: You'll have to call liquibase via "java -jar" as otherwise the system property cannot be set. You'll also need to make sure, that the liquibase-percona.jar file is on the classpath via the "--classpath" option.

When executing liquibase through maven, you can use the Properties Maven Plugin to set the system property. An example can be found in the "createIndexSkipped" integration test.

Changelog

Version 1.6.1 (????-??-??)

Version 1.6.0 (2019-04-20)

The minimum Java runtime version is now Java 1.7.

The system property liquibase.percona.options uses now a default value of --alter-foreign-keys-method=auto --nocheck-unique-key-change. These two options are not added by default anymore when pt-osc is executed. They are added now via the additional options system property. In case you have overridden this system property, make sure, to add these options as well, if you need them.

Version 1.5.2 (2019-04-14)

Version 1.5.1 (2018-11-10)

Version 1.5.0 (2018-09-30)

pt-online-schema-change is executed now with the option --nocheck-unique-key-change. This enables to add unique indexes, but can cause data loss, since duplicated rows are ignored. See Percona Toolkit Documentation for more information.

The plugin is only compatible with version 3.0.12 or later of Percona Toolkit.

Version 1.4.1 (2018-09-27)

Version 1.4.0 (2017-07-21)

Version 1.3.1 (2017-07-21)

Version 1.3.0 (2016-12-18)

Version 1.2.1 (2016-09-13)

Version 1.2.0 (2016-04-02)

Version 1.1.1 (2015-07-26)

Version 1.1.0 (2014-11-06)

Version 1.0.0 (2014-10-09)

Using / Installing the extension

Download

The jar files can be downloaded manually from maven:

http://repo.maven.apache.org/maven2/com/github/adangel/liquibase/ext/liquibase-percona/

Command line liquibase

After extracting the zip file of liquibase, place liquibase-percona-1.6.0.jar file in the sub directory lib. The shell script liquibase / liquibase.bat will automatically pick this up and the extension is available.

Via Maven

Add the following dependency to the liquibase plugin:

<dependency>
    <groupId>com.github.adangel.liquibase.ext</groupId>
    <artifactId>liquibase-percona</artifactId>
    <version>1.6.0</version>
</dependency>

Using snapshots

Snapshot builds contain the latest features which are not yet available in a release.

Download: https://oss.sonatype.org/content/repositories/snapshots/com/github/adangel/liquibase/ext/liquibase-percona/

Enable the snapshot repository via Maven:

<project>
    <pluginRepositories>
        <pluginRepository>
            <id>sonatype-nexus-snapshots</id>
            <name>Sonatype Nexus Snapshots</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>

See also https://maven.apache.org/guides/development/guide-testing-development-plugins.html.

And just use the latest SNAPSHOT version for liquibase-percona dependency, e.g. 1.6.1-SNAPSHOT:

<dependency>
    <groupId>com.github.adangel.liquibase.ext</groupId>
    <artifactId>liquibase-percona</artifactId>
    <version>1.6.1-SNAPSHOT</version>
</dependency>

Notes

The non-locking update is achieved using triggers. First a new temporary table is created, including the added or dropped columns. Then the data is copied in chunks. While the copy is in progress, any newly created or deleted or updated rows are copied, too. This is done by adding triggers to the original table. After the copy is finished, the original table is dropped and the temporary table is renamed.

This means, that pt-online-schema-change cannot be used, if the table already uses triggers.

The command pt-online-schema-change is searched only on the PATH. Depending on the property liquibase.percona.failIfNoPT the update will fail or will just run without using pt-online-schema-change and potentially lock the table for the duration of the update.

Building this extension

Simply run ./mvnw clean verify. You'll find the jar-file in the target/ subdirectory.

Integration testing

In order to execute the integration tests, run ./mvnw clean verify -Prun-its.

Please note, that you'll need:

  1. docker. During the pre-integration-test phase the official mysql image will be started. Under debian, execute sudo apt-get install docker.io.
  2. Internet access to download the docker image the first time. And to download percona toolkit. The build system will add the downloaded toolkit automatically to the PATH.
  3. The percona toolkit requires perl with mysql dbi libraries. Under debian, execute sudo apt-get install libdbd-mysql-perl.

See the properties config_... in pom.xml for connection details for the mysql docker instance.

To run a single integration test, execute maven like this: ./mvnw verify -Prun-its -Dinvoker.test=addColumn*,dropColumn

Common Problems

NoSuchMethodError: PerconaDropColumnChange.getColumns()Ljava/util/List

The full error message:

Unexpected error running Liquibase: liquibase.exception.UnexpectedLiquibaseException:
java.lang.NoSuchMethodError: liquibase.ext.percona.PerconaDropColumnChange.getColumns()Ljava/util/List;

This means, you are trying to use version 1.1.1 of the extension with liquibase 3.2.x. This is an unsupported combination. For Liquibase 3.2.x, you'll need to use liquibase-percona 1.0.0

Sponsors

Some development has been sponsored by billforward.net, a highly flexible & unified billing platform.

References