liquibase常见操作

一直以来,部门内部对于数据库结构的变更跟踪都处于一种切肤之痛,却又无暇顾及的状态。

0. 目录

      • 1. 概述
      • 2. 使用
          • 2.1 SpringBoot
          • 2.2 Maven Plugin
          • 2.3 命令行
          • 2.4 WEB Servlet
          • 2.5 spring
      • 3. changeset
      • 4. 最佳实践
      • 5. 参考

1. 概述

Liquibase 是一个用于跟踪,管理和应用数据库变化的开源的数据库重构工具。它将所有数据库的变化(包括结构和数据) 都保存在XML文件中,便于版本控制。

本文主要关注平时在liquibase使用过程中经常会遇到的一些需求和相应的对策,尝试提供一站式解决方案。

2. 使用

从官方提供的文档 可以看出,liquibase提供了多种使用方式,例如Ant,CommandLine,Maven Plugin等等。下面将挑选比较常用的来进行说明,方便读者快速入门。

2.1 SpringBoot

本文主要受众是研发人员,因此这里将与SpringBoot的集成放在首位。

其实liquibase与SpringBoot的集成可谓相当简单,因为SpringBoot的AutoConfig特性内置了对其的支持。

pom.xml

<dependency>
	<groupId>org.liquibasegroupId>
	<artifactId>liquibase-coreartifactId>
dependency>					

application.yml

spring:
  liquibase: 
    # 显式启用
    enabled: true 
    # 配置文件的路径,默认值为 classpath:/db/changelog/db.changelog-master.yaml
    # 这是总配置文件
    change-log: classpath:/db/changelog/db.changelog-master.xml 

db.changelog-master.xml 的内容形如:


<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="classpath:liquibase/changelog/sample-dsl-xml-table.xml"/>
	 <include file="classpath:liquibase/changelog/sample-dsl-xml-column.xml"/>
	<include file="classpath:liquibase/changelog/sample-dsl-xml-data.xml"/>
databaseChangeLog>

以上两步就算是完成了liquibase与SpringBoot的集成。

一些源码细节:

  1. LiquibaseAutoConfiguration。SpringBoot中对于liquibase的自动化配置入口。其中的SpringLiquibase 实现了 InitializingBean接口。
  2. LiquibaseProperties。可配置属性项的集散地。

参考链接:

  1. 官方文档 - SpringBoot集成
  2. 一起来学SpringBoot | 第二十四篇:数据库管理与迁移(Liquibase)
2.2 Maven Plugin

以笔者个人的经验,使用到Maven Plugin的时候主要是单独性地测试changesets,进行数据库对比,以及对以存在的数据库进行逆向,将其纳入版本控制中。

  1. 引入Maven Plugin

    <plugin>
    	<groupId>org.liquibasegroupId>
    	<artifactId>liquibase-maven-pluginartifactId>
    	<version>3.4.2version>
    	<configuration>
    		<changeLogFile>src/test/resources/liquibase/changelog/sample-dsl-xml-table.xmlchangeLogFile>
    		<driver>com.mysql.jdbc.Driverdriver>
    		<url>jdbc:mysql://81.xx.xxx.xx:3306/xxxxxurl>
    		<username>rootusername>
    		<password>123456password>
    		
    		<promptOnNonLocalDatabase>falsepromptOnNonLocalDatabase>					
    	configuration>
    	<executions>
    		<execution>
    			<phase>process-resourcesphase>
    			<goals>
    				<goal>updategoal>
    			goals>
    		execution>
    	executions>
    plugin>
    
  2. 常用的Maven Plugin Commands:

    # 执行某个changelog
    mvn liquibase:update -Dliquibase.changeLogFile=xxxx.xml
    
    # 对比两个数据库结构, 最终结果存放在指定位置. 注意最终的结果反映的是由源数据库结构变成目标数据库结构(由referenceUrl指示), 需要作出哪些变化.
    mvn liquibase:diff  '-Dliquibase.referenceUrl=jdbc:mysql://81.xx.xxx.xxx:3307/xxx' '-Dliquibase.referenceUsername=root' '-Dliquibase.referencePassword=123456' '-Dliquibase.diffChangeLogFile=D:/111.xml'
    
    # 逆向工程 - 生成当前数据库的changeset, 默认是生成数据库结构, 不包含数据
    mvn liquibase:generateChangeLog 
    # 逆向工程 - 生成当前数据库的changeset, 只包含数据; diffTypes的可选值可参照文档(文档的生成参见下方命令)
    mvn liquibase:generateChangeLog '-Dliquibase.diffTypes="data"'
    
    # 生成数据库结构文档
    # 生成的文档默认位于target/liquibase/dbDoc目录,入口文件为其中的index.html。
        mvn liquibase:dbDoc
    
    # 获取liquibase-maven-plugin的完整帮助文档
    mvn help:describe '-DgroupId=org.liquibase' '-DartifactId=liquibase-maven-plugin' '-Dversion=3.4.2' '-Dfull=true'
    

参考链接:

  1. 官方文档 - Maven Plugin集成
2.3 命令行

数据库的版本控制的受众不仅仅是研发类岗位,对此liquibase给出的解决方案是 CLI工具。

  1. 安装。
    首先从 liquibase CLI下载地址 下载相应操作系统版本的liquibase二进制包,笔者这里下载的是 Liquibase 4.1.0-Windows-20200928

    # 如果本地下载太慢,笔者的解决方案是找个云服务器(例如腾讯云),在上面下载完之后拉取到本地。
    wget -c https://github.com/liquibase/liquibase/releases/download/v4.1.0/liquibase-4.1.0.zip
    

    这里千万别想当然地以为是我们通过Maven方式引入的那个liquibase-core-3.8.8.jar。虽然两者的内部结构是一致的,但 Liquibase 4.1.0-Windows-20200928中不仅仅包含liquibase.jar,还附带了相应的JAR依赖,以及一组示例代码等。

  2. 配置。

    # 1. 下载的liquibase-4.1.0.zip解压到任意目录,并配置相应的环境变量Path。(笔者有强迫症,这里就以powershell下为例)
    $Env:path=$Env:Path+";D:\liquibase-4.1.0"  
    
    # 获取完整的文档信息
    liquibase --help
    
  3. 示例。

    ################################ 准备工作
    # 这里我们假设:
    #	1. 操作目录:C:\Users\{User}\Desktop\liquibase\
    #	2. liquibase-4.1.0-bin目录:D:\liquibase-4.1.0\
    # 将 liquibase.properties , changelog-dsl-xml-table.xml, mysql-connector-java-8.0.13.jar 放置到 C:\Users\{User}\Desktop\liquibase\ 下。
    
    # liquibase.properties中的内容
    	driver: com.mysql.jdbc.Driver
    	classpath: ./mysql-connector-java-8.0.13.jar
    	url: jdbc:mysql://81.68.158.66:3307/kqauth?useUnicode=true&characterEncoding=UTF-8
    	username: root
    	password: 123456    
    
    # 打开powershell, 切换到操作目录
    cd C:\Users\{
           User}\Desktop\liquibase\
    
    ################################ 常用操作
    # dbDoc : 生成数据库结构文档 ( 经过简单测试:changeLogFile参数对生成的文档没有影响,但又必须要 )
    java -jar D:\liquibase-4.1.0\liquibase.jar dbDoc D:/liquibase/ --logLevel=error --changeLogFile=changelog-dsl-xml-table.xml
    
    # update : 执行某个changelog
    java -jar D:\liquibase-4.1.0\liquibase.jar --changeLogFile=changelog-dsl-xml-table.xml update
    
    # 逆向工程 - 生成当前数据库的changeset, 默认是生成数据库结构, 不包含数据
    java -jar D:\liquibase-4.1.0\liquibase.jar --changeLogFile=generateChangeLog.xml generateChangeLog
    # 逆向工程 - 生成当前数据库的changeset, 只包含数据; diffTypes的可选值可参照文档.
    java -jar D:\liquibase-4.1.0\liquibase.jar --changeLogFile=generateChangeLog-data.xml  --diffTypes="data" generateChangeLog
    
    # 对比两个数据库结构, 最终结果存放在指定位置. 
    # 注意最终的结果反映的是由源数据库结构变成目标数据库结构(由referenceUrl指示), 需要作出哪些变化.
    java -jar D:\liquibase-4.1.0\liquibase.jar --referenceUrl=jdbc:mysql://81.68.158.66:3306/kqauth --referenceUsername=root --referencePassword=123456 --changeLogFile=D:/111.xml --diffTypes="data" diff
    

参考链接:

  1. 官方文档 - CLI集成
  2. Installing Liquibase Command Line for Windows
2.4 WEB Servlet

直接参考官方文档 - servlet-listener。

2.5 spring

对于一些历史项目,还是以spring为主的,这里提供两个参考链接:

  1. [Liquibase]集成liquibase的两种形式
  2. Liquibase+spring 初步使用

3. changeset

我们平时会使用到的主要分为两类格式 sql和xml。

文件格式 优点 缺点 参考
sql 复用SQL知识。 缺少提示,数据库强相关。 官方文档 - sql-format
xml 1. 数据库无关。
2. 有XSD(智能提示和校验)。
1. 一定的学习曲线。但在XSD提供的智能提示以及XML标签的良好命名规范下,相信这些都不会是主要障碍。 官方文档 - xml-format
  1. SQL

    
    <changeSet id="createTable" author="fulizhe">
    	<sql>
    		create table users ( id int primary key not null , name varchar(20) )
    	sql>
    	<sql>
    		insert into users ( id, name ) values (1, 'fulizhe')		
    	sql>
    changeSet>
    
    
    <changeSet id="6" author="joe"> 
    	<sqlFile path="insert-distributor-data.sql"/>
    changeSet>
    
  2. XML

    
    <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">
    
    	
    	
    	
    	<property name="now" value="now()" dbms="mysql" />
    	
    	<property name="clob.type" value="clob" dbms="oracle,postgresql"/> 
    	<property  name="clob.type" value="longtext" dbms="mysql"/> 
    
    	
    
    	
    	
    	<changeSet id="addTable" author="fulizhe">
    			
    		<preConditions onFail="MARK_RAN">
    			<not>
    				<tableExists tableName="tb2_member" />
    			not>
    		preConditions>
    		
    		<createTable tableName="tb2_member">
    			<column name="id" type="bigint" autoIncrement="true" remarks="主键">
    				<constraints primaryKey="true" nullable="false" />
    			column>	
    			<column name="mobile" type="varchar(50)" remarks="手机号">
    				<constraints nullable="false" />
    			column>
    		createTable>
    
    		
    		<addLookupTable existingTableName="tb2_member" 
    						existingColumnName="mobile" 
    						newTableName="tb2_member_COPY" 
    						newColumnName="mobile" /> 	
    	changeSet>
    
    	
    	<changeSet id="dropTable" author="fulizhe">
    		<preConditions>
    			<tableExists tableName="tb2_member" />
    		preConditions>
    		<dropTable tableName="tb2_member" />
    	changeSet>
    
    	
    	<changeSet id="renameTable" author="fulizhe">
    		<preConditions>
    			<tableExists tableName="tb2_member" />
    		preConditions>
    		
    		<renameTable 
    			oldTableName="tb2_member"
                newTableName="tb2_member2"
                /> 
    	changeSet>		
    
    	
    	
    	
    	
    	<changeSet id="addColumn" author="WATER" context="add-column">
    		<preConditions> 
    			<tableExists tableName="tb2_member" /> 
    		preConditions>
    			
    		<addColumn tableName="tb2_member">
    			<column name="nick_name" type="varchar(10)" remarks="昵称">
    			column>
    		addColumn>
    	changeSet>	
    
    	<changeSet id="modifyColumn" author="WATER" context="add-column">
    		<preConditions> 
    			<tableExists tableName="tb2_member" /> 
    		preConditions>	
    		
    		<renameColumn tableName="tb2_member" oldColumnName="nick_name"
    			newColumnName="nick_name_new" columnDataType="varchar(20)"/>
    
    		
    		<modifyDataType tableName="tb2_member" columnName="nick_name_new" newDataType="varchar(20)" />
    
    		
        	
        	
    		<addAutoIncrement
    			columnDataType="int"
    			columnName="id" 
    			incrementBy="2"  
    			startWith="100"  
    			tableName="tb2_member"/>                
    	changeSet>
    
    	
    	<createIndex 
            indexName="idx_mobile"  
            tableName="tb2_member"  
            unique="true">  
    		<column  name="mobile"/>  
    	createIndex>		
    
        <dropIndex 
                indexName="idx_mobile"         
                tableName="tb2_member"/>  
    
    	
    	<insert
    			dbms="!h2"  
    			tableName="tb2_member">  
    		<column  name="mobile"  value="132"/>  
    	insert>
    	 
        <update  tableName="tb2_member">
    	    <column name="mobile" value="address value"/>
    	    <where>id=100where>
        update>		
    
    	<delete  tableName="tb2_member">  
            <where>id=100where>  
        delete>   
    
    	    	 		
    databaseChangeLog>
    
    

参考链接:

  1. 官方文档 - change-types 其中按照被修改的对象进行了分类。
  2. 官方文档 - Basic Concepts

4. 最佳实践

这里直接借用网上资料,具体出处找不到了:

  1. ChangeSet ID 建议使用:
    a. Flayway的命名格式V[_][__description],如V1.0_0__init
    b. [任务ID]-[日期]-[序号],如T100-20190705-001
  2. ChangeSet 必须填写author。
  3. liquibase禁止对业务数据进行SQL操作。
  4. 使用的时候,禁止包含schema名称。
  5. liquibase禁止使用存储过程。
  6. 所有表,列都加remarks进行注释。
  7. 若脚本有变动,勿直接对脚本进行修改,添加修改脚本并引入。尤其是对于已经提交近SCM的脚本。
  8. 不要随意升级liquibase,特别是大版本升级。不同版本ChangeSet MD5SUM的算法不一样。

5. 参考

  1. liquibase - GitHub
  2. Liquibase使用小结
  3. 使用liquibase-maven-plugin实现持续数据库集成 这个不错!
  4. One-Stop Guide to Database Migration with Liquibase and Spring Boot

你可能感兴趣的:(DevOps,liquibase,liquibase,版本控制,数据库)