liquibase常用命令总结
Usage: java -jar liquibase.jar [options] [command] Standard Commands: update Updates database to current version updateSQL Writes SQL to update database to current version to STDOUT updateCount <num> Applies next NUM changes to the database updateCountSQL <num> Writes SQL to apply next NUM changes to the database updateToTag <tag> Updates the database to the changeSet with the specified tag updateToTagSQL <tag> Writes (to standard out) the SQL to update to the changeSet with the specified tag rollback <tag> Rolls back the database to the the state is was when the tag was applied rollbackSQL <tag> Writes SQL to roll back the database to that state it was in when the tag was applied to STDOUT rollbackToDate <date/time> Rolls back the database to the the state is was at the given date/time. Date Format: yyyy-MM-dd'T'HH:mm:ss rollbackToDateSQL <date/time> Writes SQL to roll back the database to that state it was in at the given date/time version to STDOUT rollbackCount <value> Rolls back the last <value> change sets applied to the database rollbackCountSQL <value> Writes SQL to roll back the last <value> change sets to STDOUT applied to the database futureRollbackSQL Writes SQL to roll back the database to the current state after the changes in the changeslog have been applied futureRollbackSQL <value> Writes SQL to roll back the database to the current state after <value> changes in the changeslog have been applied futureRollbackFromTagSQL <tag> Writes (to standard out) the SQL to roll back the database to its current state after the changes up to the specified tag have been applied updateTestingRollback Updates database, then rolls back changes before updating again. Useful for testing rollback support generateChangeLog Writes Change Log XML to copy the current state of the database to standard out snapshot Writes the current state of the database to standard out snapshotReference Writes the current state of the referenceUrl database to standard out Diff Commands diff [diff parameters] Writes description of differences to standard out diffChangeLog [diff parameters] Writes Change Log XML to update the database to the reference database to standard out Documentation Commands dbDoc <outputDirectory> Generates Javadoc-like documentation based on current database and change log Maintenance Commands tag <tag string> 'Tags' the current database state for future rollback tagExists <tag string> Checks whether the given tag is already existing status [--verbose] Outputs count (list if --verbose) of unrun changesets unexpectedChangeSets [--verbose] Outputs count (list if --verbose) of changesets run in the database that do not exist in the changelog. validate Checks changelog for errors calculateCheckSum <id> Calculates and prints a checksum for the changeset with the given id in the format filepath::id::author. clearCheckSums Removes all saved checksums from database log. Useful for 'MD5Sum Check Failed' errors changelogSync Mark all changes as executed in the database changelogSyncSQL Writes SQL to mark all changes as executed in the database to STDOUT markNextChangeSetRan Mark the next change changes as executed in the database markNextChangeSetRanSQL Writes SQL to mark the next change as executed in the database to STDOUT listLocks Lists who currently has locks on the database changelog releaseLocks Releases all locks on the database changelog dropAll Drop all database objects owned by user Required Parameters: --changeLogFile=<path and filename> Migration file --username=<value> Database username --password=<value> Database password. If values is PROMPT, Liquibase will prompt for a password --url=<value> Database URL Optional Parameters: --classpath=<value> Classpath containing migration files and JDBC Driver --driver=<jdbc.driver.ClassName> Database driver class name --databaseClass=<database.ClassName> custom liquibase.database.Database implementation to use --propertyProviderClass=<properties.ClassName> custom Properties implementation to use --defaultSchemaName=<name> Default database schema to use --contexts=<value> ChangeSet contexts to execute --labels=<expression> Expression defining labeled ChangeSet to execute --defaultsFile=</path/to/file.properties> File with default option values (default: ./liquibase.properties) --delimiter=<string> Used with executeSql command to set the string used to break up files that consist of multiple statements. --driverPropertiesFile=</path/to/file.properties> File with custom properties to be set on the JDBC connection to be created --changeExecListenerClass=<ChangeExecListener.ClassName> Custom Change Exec listener implementation to use --changeExecListenerPropertiesFile=</path/to/file.properties> Properties for Custom Change Exec listener --liquibaseCatalogName=<name> The name of the catalog with the liquibase tables --liquibaseSchemaName=<name> The name of the schema with the liquibase tables --databaseChangeLogTableName=<name> The name of the Liquibase ChangeLog table (default: DATABASECHANGELOG) --databaseChangeLogLockTableName=<name> The name of the Liquibase ChangeLog Lock table (default: DATABASECHANGELOGLOCK) --liquibaseSchemaName=<name> The name of the schema with the liquibase tables --includeSystemClasspath=<true|false> Include the system classpath in the Liquibase classpath (default: true) --promptForNonLocalDatabase=<true|false> Prompt if non-localhost databases (default: false) --logLevel=<level> Execution log level (debug, info, warning, severe, off --logFile=<file> Log file --currentDateTimeFunction=<value> Overrides current date time function used in SQL. Useful for unsupported databases --outputDefaultSchema=<true|false> If true, SQL object references include the schema name, even if it is the default schema. Defaults to true --outputDefaultCatalog=<true|false> If true, SQL object references include the catalog name, even if it is the default catalog. Defaults to true --outputFile=<file> File to write output to for commands that write output, e.g. updateSQL. If not specified, writes to sysout. --help Prints this message --version Prints this version information Required Diff Parameters: --referenceUsername=<value> Reference Database username --referencePassword=<value> Reference Database password. If value is PROMPT, Liquibase will prompt for a password --referenceUrl=<value> Reference Database URL Optional Diff Parameters: --defaultCatalogName=<name> Default database catalog to use --defaultSchemaName=<name> Default database schema to use --referenceDefaultCatalogName=<name> Reference database catalog to use --referenceDefaultSchemaName=<name> Reference database schema to use --schemas=<name1,name2> Database schemas to include objects from in comparison --referenceSchemas=<name1,name2> Reference database schemas to include objects from in comparison only needed if different than --schemas --outputSchemaAs=<name1,name2> On diffChangeLog/generateChangeLog, use these names as schemaName instead of the real names. --includeCatalog=<true|false> If true, the catalog will be included in generated changeSets Defaults to false --includeSchema=<true|false> If true, the schema will be included in generated changeSets Defaults to false --referenceDriver=<jdbc.driver.ClassName> Reference database driver class name --dataOutputDirectory=DIR Output data as CSV in the given directory --diffTypes List of diff types to include in Change Log expressed as a comma separated list from: tables, views, columns, indexes, foreignkeys, primarykeys, uniqueconstraints data. If this is null then the default types will be: tables, views, columns, indexes, foreignkeys, primarykeys, uniqueconstraints. Change Log Properties: -D<property.name>=<property.value> Pass a name/value pair for substitution in the change log(s) Default value for parameters can be stored in a file called 'liquibase.properties' that is read from the current working directory. Full documentation is available at http://www.liquibase.org/documentation/command_line.html Process finished with exit code 0
生成某个changeSet的md5Sum
<changeSet author="alexy" id="bizbase-20181113-1811" dbms="mysql"> <preConditions onFail="MARK_RAN"> <not> <columnExists schemaName="${schema.dlsys}" tableName="tc_wf_trans_def" columnName="trans_priority" ></columnExists> </not> </preConditions> <addColumn schemaName="${schema.dlsys}" tableName="tc_wf_trans_def"> <column name="trans_priority" type="int" defaultValue="-100"/> </addColumn> <addColumn schemaName="${schema.dlsys}" tableName="temp_trans_inst"> <column name="trans_priority" type="int"/> </addColumn> </changeSet>
public CheckSum generateCheckSum() { if (checkSum == null) { StringBuffer stringToMD5 = new StringBuffer(); for (Change change : getChanges()) { stringToMD5.append(change.generateCheckSum()).append(":"); } for (SqlVisitor visitor : this.getSqlVisitors()) { stringToMD5.append(visitor.generateCheckSum()).append(";"); } checkSum = CheckSum.compute(stringToMD5.toString()); } return checkSum; }
注意:Change接口有generateCheckSu()方法有多个子类重写了。
changeSet的id规则
logicalFilePath
<?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog logicalFilePath="META-INF/resources/bizbase-db-changelog.xml" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
或者<changeSet>标签内:
<changeSet author="alexy" id="bizbase-20181113-1811" dbms="mysql" logicalFilePath="META-INF/resources/bizbase-db-changelog.xml"> <preConditions onFail="MARK_RAN"> <not> <columnExists schemaName="${schema.dlsys}" tableName="tc_wf_trans_def" columnName="trans_priority" ></columnExists> </not> </preConditions> <addColumn schemaName="${schema.dlsys}" tableName="tc_wf_trans_def"> <column name="trans_priority" type="int" defaultValue="-100"/> </addColumn> <addColumn schemaName="${schema.dlsys}" tableName="temp_trans_inst"> <column name="trans_priority" type="int"/> </addColumn> </changeSet>
问题1:修改changeSet,避免md5Sum校验问题
当一个changelog执行后,则会为在databasechangelog表中为每一个changeSet生成一个md5Sum。如果我们后面因为某些原因再次修改通一个changeSet就会有类似下面的报错:
2017-05-06 10:52:15,082 | ERROR | Error while applying liquibase changelogs db/changelog/wiki.db.changelog-1.0.0.xml - Cause : Validation Failed: 1 change sets check sum db/changelog/wiki.db.changelog-1.0.0.xml::1.0.0-42::wiki is now: 7:21d239448c33f39a9300ea433349d470
这是因为liquibase每次启动都会将已执行的changeSet与changelog.xml中的id相同的changeSet进行md5Sum比较,如果你修改了某个changeSet,而导致md5Sum的改变就会有上面的报错了。
解决办法:
方法1.使用使用<validCheckSum>标签。
使用具体的md5Sum,该值既可以从报错中获得,也可以直接使用liquibase的calculateCheckSum命令来生成。
<changeSet id="1.0.0-42" author="wiki"> <validCheckSum>7:21d239448c33f39a9300ea433349d470</validCheckSum> … // content of the changeset (with the update) </changeSet>
或者
<changeSet id="1.0.0-42" author="wiki"> <validCheckSum>any</validCheckSum> … // content of the changeset (with the update) </changeSet>
或者
<changeSet id="1.0.0-42" author="wiki"> <validCheckSum>*</validCheckSum> … // content of the changeset (with the update) </changeSet>
或者
<changeSet id="1.0.0-42" author="wiki"> <validCheckSum>all</validCheckSum> … // content of the changeset (with the update) </changeSet>
方法2. 手动修改databasechangelog表中的数据
自己去databasechangelog表中,将对应的changeSet的md5Sum字段改为最新的md5值或者是把该字段清空。
官方的文档有些不是很详细,最好的办法是直接看Liquibase的源代码,下面附上liquibase中changeSet的md5Sum比对的代码和注释:
liquibase/changelog/ChangeSet.java:
public boolean isCheckSumValid(CheckSum storedCheckSum) { //注意:storedCheckSum:databasechangelog表中该changeSet的md5Sum值。 //validCheckSums : 即<validCheckSum>标签的值所组成的列表,既然是列表,则说明一个changeSet元素可以添加多个<validCheckSum>标签 // no need to generate the checksum if any has been set as the valid checksum for (CheckSum validCheckSum : validCheckSums) { //如果<validCheckSum>标签的值为“any”,“all”或者“*”,则认为该changeSet没有修改过 if (validCheckSum.toString().equalsIgnoreCase("1:any") || validCheckSum.toString().equalsIgnoreCase("1:all") || validCheckSum.toString().equalsIgnoreCase("1:*")) { return true; } } //currentMd5Sum : 表示当前changeSet的md5Sum值 CheckSum currentMd5Sum = generateCheckSum(); //currentMd5Sum为空,则返回true if (currentMd5Sum == null) { return true; } //storedCheckSum(意思是表里的md5Sum)为空,则返回true if (storedCheckSum == null) { return true; } //如果表里的与xml中的md5Sum一致,则返回true if (currentMd5Sum.equals(storedCheckSum)) { return true; } //或者是当前xml中changeSet的md5Sum值与任何一个<validCheckSum>标签的值相等时,则返回true for (CheckSum validCheckSum : validCheckSums) { if (currentMd5Sum.equals(validCheckSum) || storedCheckSum.equals(validCheckSum)) { return true; } } return false; }
问题2 表字段名中包含关键字,导致sql执行失败
由于有些表的字段与数据库的关键字一样,就会导致sql执行失败,我们需要将这些字段用反引号(quotetick)包裹起来,liquibase为我们提供了配置项。
可以在 “<databaseChangeLog> 或者 <changeset>中加入 objectQuotingStrategy=”QUOTE_ALL_OBJECTS” 属性。
如下:
<?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog logicalFilePath="META-INF/resources/bizbase-db-changelog.xml" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd" objectQuotingStrategy="QUOTE_ALL_OBJECTS" >
或
<changeSet id="bizbase-20190413-1541" author="dabu" objectQuotingStrategy="QUOTE_ALL_OBJECTS"> <insert tableName="testquote"> <column name="join">xxx</column> </insert> </changeSet>
objectQuotingStrategy有三种策略:
- LEGACY //默认策略
- QUOTE_ALL_OBJECTS //对所有字段加反引号(建议使用)
- QUOTE_ONLY_RESERVED_WORDS //只对关键字加反引号
测试如下:
当objectQuotingStrategy=”QUOTE_ALL_OBJECTS ” ,使用liquibase的updateSQL,输出如下:
-- Changeset META-INF/resources/bizbase-db-changelog.xml::bizbase-20190413-1541::xxxx INSERT INTO `cgdb1025`.`testquote` (`join`) VALUES ('xxx');
总结:
公司用了liquibase后遇到不少问题,但是感觉貌似他们也不是太熟悉Liquibase的用法之类的,索性抽个时间看了下Liquibase的源代码,其中md5Sum的值的计算方式比我想的要复杂,看来果然还是不能瞎猜。看了Liquibase代码后,在为知笔记了写了点笔记,很乱,所以本文只是从笔记中抽出了部分整理后放到博客上,希望对大家有用,后面可能会不定期更新吧,有问题可以留言,我尽力解答。
请教一个问题,我初始化完以后,总是提示 Table ‘databasechangelog’ already exists这个错误,用的是mysql5.7
liquibase版本是多少? 官方说3.4.X的版本schema有bug,mysql会忽略。