LiquiBase是一個用於數據庫重構和遷移的開源工具,通過日志文件的形式記錄數據庫的變更,然后執行日志文件中的修改,將數據庫更新或回滾到一致的狀態。LiquiBase的主要特點有:
- 支持幾乎所有主流的數據庫,如MySQL, PostgreSQL, Oracle, Sql Server, DB2等;
- 支持多開發者的協作維護;
- 日志文件支持多種格式,如XML, YAML, JSON, SQL等;
- 支持多種運行方式,如命令行、Spring集成、Maven插件、Gradle插件等;
changelog文件格式
changelog是LiquiBase用來記錄數據庫的變更,一般放在CLASSPATH下,然后配置到執行路徑中。
changelog支持多種格式,主要有XML/JSON/YAML/SQL,其中XML/JSON/YAML除了具體格式語法不同,節點配置很類似,SQL格式中主要記錄SQL語句,這里僅給出XML格式和SQL格式的示例,更多的格式示例請參考文檔
changelog.xml
<changeSet author="admin" id="1496901181769-1"> <createTable schemaName="ihome" tableName="test"> <column autoIncrement="true" name="id" type="INT"> <constraints primaryKey="true"/> </column> <column name="name" type="VARCHAR(10)"/> </createTable> </changeSet>
changelog.sql
--liquibase formatted sql --changeset daniel:16040707 CREATE TABLE `role_authority_sum` ( `row_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `role_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '關聯role的role_id', `authority_sum` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'perms的值的和', `data_type_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '關聯data_type的id', PRIMARY KEY (`row_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色的權限值的和,如角色有RD權限,則和為2+8=10';
在執行changelog的時候,會在數據庫記錄執行記錄,主要用了下面的兩張表:
- databasechangelog
- databasechangeloglock
常用的標簽及命令
1. 標簽
一個<changeSet>標簽對應一個變更集,由屬性id、name,以及changelog的文件路徑唯一標識。changelog在執行的時候並不是按照id的順序,而是按照changeSet在changelog中出現的順序。
changelog中的一個changeSet對應一個事務,在changeSet執行完后commit,如果出現錯誤則rollback。
2. <include>與<includeAll>標簽
<include>的file屬性表示要包含的changelog文件的路徑,這個文件可以是LiquiBase支持的任意格式,relativeToChangelogFile如果為true,則表示file屬性表示的文件路徑是相對於根changelog而不是CLASSPATH的,默認為false。
<includeAll>指定的是changelog的目錄,而不是為文件,如:
<includeAll path="com/example/changelogs/"/>
注意: 目前<include>沒有解決重復引用和循環引用的問題,重復引用還好,LiquiBase在執行的時候可以判斷重復,而循環引用會導致無限循環,需要注意!
3. 生成已有數據庫的changelog
有兩種方式,一種是使用數據庫工具導出SQL數據,然后changelog文件以SQL格式記錄即可;另一種方式就是用generateChangeLog命令,如:
liquibase --driver=com.mysql.jdbc.Driver \ --classpath=./mysql-connector-java-5.1.29.jar \ --changeLogFile=liquibase/db.changelog.xml \ --url="jdbc:mysql://127.0.0.1:3306/test" \ --username=root \ --password=yourpass \ generateChangeLog
不過generateChangeLog不支持以下功能:存儲過程、函數以及觸發器;
生成文件的路徑可以設置:
<plugin> <groupId>org.liquibase</groupId> <artifactId>liquibase-maven-plugin</artifactId> <version>3.4.2</version> <configuration> <propertyFile>src/main/resources/liquibase.properties</propertyFile> <propertyFileWillOverride>true</propertyFileWillOverride> <!--生成文件的路徑--> <outputChangeLogFile>src/main/resources/changelog_dev.xml</outputChangeLogFile> </configuration> </plugin>
也可以配置在properties文件中:
changeLogFile=src/main/resources/db/changelog/db.changelog-master.xml driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&useSSL=false&jdbcCompliantTruncation=false username=root password=123456 verbose=true ## 生成文件的路徑 outputChangeLogFile=src/main/resources/changelog_dev.xml
Maven集成
liquibase-maven-plugin的配置
如果需要在父項目中配置子項目共享的LiquiBase配置,而各個子項目可以定義自己的配置,並覆蓋父項目中的配置,則只需要在父項目的pom中將propertyFileWillOverride設置為true即可,如:
<plugin> <groupId>org.liquibase</groupId> <artifactId>liquibase-maven-plugin</artifactId> <version>3.4.2</version> <configuration> <propertyFileWillOverride>true</propertyFileWillOverride> <propertyFile>src/main/resources/liquibase.properties</propertyFile> </configuration> </plugin>
## 執行changelog中的變更
liquibase:update
## rollback
liquibase:rollback
rollback有3中形式,分別是:
- rollbackCount: 表示rollback的changeset的個數;
- rollbackDate:表示rollback到指定的日期;
- rollbackTag:表示rollback到指定的tag,需要使用LiquiBase在具體的時間點打上tag;
liquibase:rollback -Dliquibase.rollbackCount=3
rollbackDate需要注意日期的格式,必須匹配當前平台上執行DateFormat.getDateInstance()得到的格式,比如我的格式為MMM d, yyyy,示例如:
liquibase:rollback -Dliquibase.rollbackDate="Apr 10, 2016"
rollbackTag使用tag標識,所以需要先打tag,示例如:
liquibase:tag -Dliquibase.tag=tag20160410
然后rollback到tag20160410,如:
liquibase:rollback -Dliquibase.rollbackTag=tag20160410
最佳實踐
1. 如何管理changeLogs
按照主要的release版本號管理你的changeLogs
com example db changelog db.changelog-master.xml db.changelog-1.0.xml db.changelog-1.1.xml db.changelog-2.0.xml DatabasePool.java AbstractDAO.java
db.changelog-master.xml
該文件包含了所有的release版本的changeLog,並按照正確的順序引入進來:
<?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.1.xsd"> <include file="com/example/db/changelog/db.changelog-1.0.xml"/> <include file="com/example/db/changelog/db.changelog-1.1.xml"/> <include file="com/example/db/changelog/db.changelog-2.0.xml"/> </databaseChangeLog>
2. Managing Stored Procedures
Try to maintain separate changelog for Stored Procedures and use runOnChange=”true”. This flag forces LiquiBase to check if the changeset was modified. If so, liquibase executes the change again.
3. One Change per ChangeSet
As far as possible, Avoid multiple changes per changeset to avoid failed autocommit statements that can leave the database in an unexpected state
4. ChangeSet Ids
Choose what works for you. Some use a sequence number starting from 1 and unique within the changelog, some choose a descriptive name (e.g. ‘new-address-table’).
5. Document ChangeSets
Use <comments> in the change sets. They say “A stitch in time saves nine!”
6. Always think about rollback
Try to write changesets in a way that they can be rolled back. e.g. use relevant change clause instead of using custom <sql> tag. Include a <rollback> clause whenever a change doesn’t support out of box rollback. (e.g. <sql>, <insert>, etc)
7. Reference Data Management
Leverage Liquibase to manage your Reference Data. Environment separation (DEV, QA, PROD) can be achieved using “context”.
8. Procedure for the developer
- Using your favorite IDE or editor, create a new local changeSet containing the change;
- Run Liquibase to execute the new changeSet (this tests the SQL code);
- Perform the corresponding changes in the application code (e.g., Java code);
- Test the new application code together with the database change;
- Commit both the changeSet and the application code.
問題
'changeLogFile' in properties file is not being used by this task.
鏈接