数据库迁移工具-Liquibase使用

介绍

Liquibase是一个用于数据库重构和迁移的开源工具,通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态。它的目标是提供一种数据库类型无关的解决方案,通过执行schema类型的文件来达到迁移。其有点主要有以下:

  1. 支持几乎所有主流的数据库,如MySQL, PostgreSQL, Oracle, Sql Server, DB2等;
  2. 支持多开发者的协作维护;
  3. 日志文件支持多种格式,如XML, YAML, JSON, SQL等;
  4. 支持多种运行方式,如命令行、Spring集成、Maven插件、Gradle插件等。

快速使用

Springboot中

引入依赖

<dependencies>
    <dependency>
        <groupId>org.liquibase</groupId>
        <artifactId>liquibase-core</artifactId>
    </dependency>
    <dependency>
</dependencies>

配置日志文件ChangeLog

  1. resources目录中创建/db/changelog目录作为日志文件存放目录
  2. 在目录中创建日志文件db.changelog-master.yml
  3. application.yml中配置changelog路径
spring:
  liquibase: 
    # 不配置默认会查找'classpath:/db/changelog/db.changelog-master.yaml'文件
    change-log: 'classpath:/db/changelog/db.changelog-master.yml'

编写变更记录ChangeSet

  1. 编写初始数据库脚本
databaseChangeLog:
  - changeSet:
      # 唯一id,建议使用Flayway的命名格式'V<version>[_<SEQ>][__description]'
      id: V1.0_0__init
      # 作者
      author: Cheivin
      # 描述
      comment: "初始化脚本内容,加载初始数据"
      # 启用事物
      runInTransaction: true
      # 变更脚本
      changes:
        # 创建表格
        - createTable:
            tableName: user
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
                  remarks:
              - column:
                  name: username
                  type: VARCHAR(50)
                  constraints:
                    nullable: false
              - column:
                  name: password
                  type: VARCHAR(50)
                  constraints:
                    nullable: false
        # 加载数据
        - loadData:
            tableName: user
            columns:
              - column:
                  header: username
                  name: username
              - column:
                  header: password
                  name: password
            encoding: UTF-8
            file: db/data/init-data.csv
        # 标记,用于回滚时指定版本
        - tagDatabase:
            tag: V1.0_0__init
  1. 运行项目后,查看数据库
  2. 修改changelog,增加变更数据库脚本
# 在databaseChangeLog后追加
  - changeSet:
      id: V1.0_1__mod
      author: Cheivin
      comment: "修改用户表,增加账单表"
      runInTransaction: true
      changes:
        # 通过标准格式添加字段
        - addColumn:
            # 目标表
            tableName: user
            columns:
              - column:
                  name: state
                  type: tinyint
                  # 默认值
                  defaultValueNumeric: 0
                  remarks: '用户状态,0:未激活,1:激活,-1:禁用'
              - column:
                  name: identity
                  type: int
                  # 默认值
                  defaultValueNumeric: 999
                  remarks: '用户身份,999:管理员'
        # 通过sql语句操作数据库
        - sql:
            sql: insert into user (username,password,state,identity) values ('admin','admin',1,999)
        # 通过sql文件操作数据库
        - sqlFile:
            encoding: utf8
            path: db/changelog/V1.0_1__mod_bill.sql
        - tagDatabase:
            tag: V1.0_1__mod
        # 回滚语句
        - rollback:
            - delete:
                tableName: user
                where: username='admin'
            - dropTable:
                tableName: user_bill

Maven中

引入依赖

<build>
    <plugins>
        <plugin>
            <groupId>org.liquibase</groupId>
            <artifactId>liquibase-maven-plugin</artifactId>
            <version>3.6.3</version>
            <configuration>
              <!-- 配置文件,必须放在resource目录下 -->
              <propertyFile>src/main/resources/liquibase/liquibase.properties</propertyFile>
            </configuration>
            <executions>
                <!-- 默认mvn启动时执行更新操作 -->
                <execution>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>update</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

配置liquibase.properties

# 日志文件路径,必须放在resource目录下
changeLogFile=src/main/resources/liquibase/db.changelog-master.yml
# 数据库地址
url=jdbc:mysql://localhost:3306/liquibase_mvn?useSSL=false&useUnicode=true&characterEncoding=UTF-8
# 账号
username=root
# 密码
password=root

编写变更记录ChangeSet

  1. 编写初始数据库脚本
databaseChangeLog:
  - changeSet:
      # 唯一id,建议使用Flayway的命名格式'V<version>[_<SEQ>][__description]'
      id: V1.0_0__init
      # 作者
      author: Cheivin
      # 描述
      comment: "初始化脚本内容,加载初始数据"
      # 启用事物
      runInTransaction: true
      # 变更脚本
      changes:
        # 创建表格
        - createTable:
            tableName: user
            remarks: '用户表'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: username
                  type: VARCHAR(50)
                  constraints:
                    nullable: false
                  remarks: '用户名'
              - column:
                  name: password
                  type: VARCHAR(50)
                  constraints:
                    nullable: false
                  remarks: '密码'
        # 加载数据
        - loadData:
            tableName: user
            columns:
              - column:
                  header: username
                  name: username
              - column:
                  header: password
                  name: password
            encoding: UTF-8
            file: src/main/resources/liquibase/data/init-data.csv
        # 标记,用于回滚时指定版本
        - tagDatabase:
            tag: V1.0_0__init
  1. 运行项目后,查看数据库
  2. 修改changelog,增加变更数据库脚本
# 在databaseChangeLog后追加
  - changeSet:
      id: V1.0_1__mod
      author: Cheivin
      comment: "修改用户表,增加账单表"
      runInTransaction: true
      changes:
        # 通过标准格式添加字段
        - addColumn:
            # 目标表
            tableName: user
            columns:
              - column:
                  name: state
                  type: tinyint
                  # 默认值
                  defaultValueNumeric: 0
                  remarks: '用户状态,0:未激活,1:激活,-1:禁用'
              - column:
                  name: identity
                  type: int
                  # 默认值
                  defaultValueNumeric: 999
                  remarks: '用户身份,999:管理员'
        # 通过sql语句操作数据库
        - sql:
            sql: insert into user (username,password,state,identity) values ('admin','admin',1,999)
        # 通过sql文件操作数据库
        - sqlFile:
            encoding: utf8
            path: src/main/resources/liquibase/V1.0_1__mod_bill.sql
        - tagDatabase:
            tag: V1.0_1__mod
        # 回滚语句
        - rollback:
            - delete:
                tableName: user
                where: username='admin'
            - dropTable:
                tableName: user_bill

版本回滚

回滚指定次数

命令格式

mvn liquibase:rollback -Dliquibase.rollbackCount=次数

eg:

mvn liquibase:rollback -Dliquibase.rollbackCount=1

回滚到指定tag

命令格式

mvn liquibase:rollback -Dliquibase.rollbackTag=tag名称

eg:

mvn liquibase:rollback -Dliquibase.rollbackTag=V1.0_0__init

输出回滚语句

命令格式

mvn liquibase:rollbackSQL -Dliquibase.rollbackCount=次数

mvn liquibase:rollbackSQL -Dliquibase.rollbackTag=tag名称

将会在target/liquibase目录中生成migrate.sql文件

输出变更记录

命令格式

mvn liquibase:dbDoc

将会在target/liquibase目录中生成dbDoc目录,打开index.html可查看

一些规范

  1. ChangeSet id建议使用Flayway的命名格式V<version>[_<SEQ>][__description],如V1.0_0__init。或使用[任务ID]-[日期]-[序号],如T100-20190705-001
  2. ChangeSet必须填写author
  3. Liquibase禁止对业务数据进行sql操作
  4. 所有表,列要加remarks进行注释
  5. 已经执行过的ChangeSet严禁修改。
  6. 不要随便升级项目liquibase版本,特别是大版本升级。不同版本ChangeSet MD5SUM的算法不一样。

参考资料

  1. 官方文档
  2. changeset配置文档
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容