最新消息:

Liquibase常见问题总结

Java ksharpdabu 20799浏览 0评论

liquibase常用命令总结

生成某个changeSet的md5Sum

md5Sum生成规则(md5Sum与filepath无关)
如果一个changeSet中有多个操作,如下:

则liquibase会为每个<addColumn>生成一个md5(这里有两个addColumn对象),然后拼接这两个对象的md5,再生成整个changeLog对象的md5Sum。
见:liquibase.changelog.ChangeSet#generateCheckSum

注意:Change接口有generateCheckSu()方法有多个子类重写了。

changeSet的id规则

liquibase判断两个changset是否是同一个就是根据id来判断的。id是由“filepath::id::author”组成的。对应databasechangelog表中的以下字段:

logicalFilePath

假设有A和B两个项目,如果我想用B项目单独测试A项目的某个changeSet,我新建一个B/changelog.xml文件,存放待验证的changeset。但是 A项目的FilePath(changelog文件到路径为) A/a-changelog.xml 。而liquibase判断两个changset是否是同一个就是根据id来判断的,id是由“filepath::id::author”组成的,所以如果A和B的filepath(即changelog.xml文件路径)不同,则liquibase就不会认为这个同一个changeset了。所以,这就是logicalFilePath属性的意义。
可以放在<databaseChangeLog>标签内,即整个changelog.xml都会用这个作为逻辑地址。

或者<changeSet>标签内:

 

问题1:修改changeSet,避免md5Sum校验问题

当一个changelog执行后,则会为在databasechangelog表中为每一个changeSet生成一个md5Sum。如果我们后面因为某些原因再次修改通一个changeSet就会有类似下面的报错:

这是因为liquibase每次启动都会将已执行的changeSet与changelog.xml中的id相同的changeSet进行md5Sum比较,如果你修改了某个changeSet,而导致md5Sum的改变就会有上面的报错了。

解决办法:

方法1.使用使用<validCheckSum>标签。

使用具体的md5Sum,该值既可以从报错中获得,也可以直接使用liquibase的calculateCheckSum命令来生成。

或者

或者

或者

方法2. 手动修改databasechangelog表中的数据

自己去databasechangelog表中,将对应的changeSet的md5Sum字段改为最新的md5值或者是把该字段清空。

官方的文档有些不是很详细,最好的办法是直接看Liquibase的源代码,下面附上liquibase中changeSet的md5Sum比对的代码和注释

liquibase/changelog/ChangeSet.java:

 

问题2  表字段名中包含关键字,导致sql执行失败

由于有些表的字段与数据库的关键字一样,就会导致sql执行失败,我们需要将这些字段用反引号(quotetick)包裹起来,liquibase为我们提供了配置项。

可以在 “<databaseChangeLog> 或者 <changeset>中加入 objectQuotingStrategy=”QUOTE_ALL_OBJECTS” 属性。

如下:

 

objectQuotingStrategy有三种策略:

  • LEGACY //默认策略
  • QUOTE_ALL_OBJECTS //对所有字段加反引号(建议使用)
  • QUOTE_ONLY_RESERVED_WORDS  //只对关键字加反引号

测试如下:

当objectQuotingStrategy=”QUOTE_ALL_OBJECTS ” ,使用liquibase的updateSQL,输出如下:

 

 

 


总结:

公司用了liquibase后遇到不少问题,但是感觉貌似他们也不是太熟悉Liquibase的用法之类的,索性抽个时间看了下Liquibase的源代码,其中md5Sum的值的计算方式比我想的要复杂,看来果然还是不能瞎猜。看了Liquibase代码后,在为知笔记了写了点笔记,很乱,所以本文只是从笔记中抽出了部分整理后放到博客上,希望对大家有用,后面可能会不定期更新吧,有问题可以留言,我尽力解答。

转载请注明:大步's Blog » Liquibase常见问题总结

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (5)

  1. 请教一个问题,我初始化完以后,总是提示 Table 'databasechangelog' already exists这个错误,用的是mysql5.7
    hecheng3年前 (2020-04-07)Reply
    • liquibase版本是多少? 官方说3.4.X的版本schema有bug,mysql会忽略。
      ksharpdabu3年前 (2020-04-11)Reply
  2. 谢谢分享
    江东去3年前 (2020-11-20)Reply
  3. liquibase死锁,waiting for changelog lock。。。这个问题的根本原因是什么,难道每次都要手动修改表,去释放锁资源么
    kkkdjf2年前 (2021-01-21)Reply
    • 1.遇到这种情况,一般是多台服务在同时执行liquibase,导致lock, 比如多台web同时启动。 解决办法:可以先单独启动一台,再启动其他的实例。 2. 但是根本可能是changelog中有大表的DDL语句,比如有的大表加字段。我们公司的有统计表加一个字段,要花三个小时才执行成功,这种就会lock很久,web服务半天启动不了。这种就需要公司定好规范,把大表的DDL语句单独弄出来,放到一条sql中执行,避免加三个字段就执行三次sql这种情况。 3.还有遇到过lock后,直接kill tomcat进程,导致liquibase lock没还锁着,下次启动服务,依旧锁。 liquibase有listLocks 和releaseLocks ,可以查看锁和释放锁 ,可以看文章里的命令
      ksharpdabu2年前 (2021-01-24)Reply