方式一:使用管理工具/插件
工具一:flyway
1.原理
1)在目标数据库的database中创建一张表flyway_schema_history用于管理当前数据库的版本; 2)每次数据库版本升级,即执行了一些DDL或DML之后,就会将本次执行脚本与对应版本号记录到该表中; 3)每次启动服务时,都会检查是否有版本大于flyway_schema_history中最新版本号的脚本,有则执行并再次记录。
2.使用规范
- 所有脚本目录均放置于src/main/resources的db/[业务空间]下,业务空间是区分不同业务模块的英文名,通常与数据库database对应,如raven。
- 脚本命名规则遵循V[版本号]__[业务空间]_[自定义名称].sql,例如V1.0.0__raven_init.sql,注意版本号后面是两个下划线。
- 上述版本号与springboot工程版本号应当统一,例如某个springboot工程的第一个正式版本是1.0.0-RELEASE,那么对应的脚本文件中的版本号也应该是1.0.0
3.基本使用
1)在springboot工程中,添加flyway的依赖
<!-- 引入 flywaydb 用于数据库版本控制 --> <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> <version>5.2.4</version> </dependency>
2)在工程的application.yml中添加配置:
spring: flyway: enabled: true # locations指明了用于存放sql脚本的资源目录 locations: - "classpath:db/[业务空间]/" # 当目标数据库非空且没有`flyway_schema_history`表时,是否自动执行baseline操作以此时数据库及locations的状态作为基线 baseline-on-migrate: true # baseline-on-migrat触发时的基准版本,如果已经部署的服务的版本是"1.0.1",那么这里就设置为"1.0.1",这样locations中版本小于等于"1.0.1"的脚本将不会被执行 baseline-version: 0
3)配置属性: • spring.flyway.enabled:是否开启flyway,默认为true。springboot已经在其底层依赖包spring-boot-autoconfigure中,通过一个名叫FlywayAutoConfiguration的@Configuration组件按条件加载flyway组件。加载的条件是:Flyway这个类存在,且数据源组件DataSource存在,且spring.flyway.enabled为true。 • spring.flyway.locations:flyway读取sql脚本的资源目录,当一个springboot项目首次被部署并启动时,flyway会在目标数据库的database下创建一个名为flyway_schema_history的表,并读取这里配置的locations下的sql脚本(注意脚本名要满足约定)。 • baseline-on-migrate与 baseline-version:有时我们首次部署项目时还没有使用flyway,后面想引入flyway时,就需要先做一个基线版本的记录,此时就需要用到这两个配置。baseline-on-migrate用来指示当目标数据库非空且没有flyway_schema_history表时,是否自动执行数据库的基线版本的记录。所谓基线BaseLine,就是数据库起始版本。 baseline-version就是基线版本号。此时flyway在创建好flyway_schema_history表之后,会触发基线版本操作,将 baseline-version配置的版本号作为基线版本插入flyway_schema_history表;然后执行locations中版本号大于基线版本的脚本并记录这些版本。
4.插件使用
flyway插件通常只在开发与测试环境中使用,在工程pom的plugins中添加如下配置:
<plugin> <groupId>org.flywaydb</groupId> <artifactId>flyway-maven-plugin</artifactId> <version>5.2.4</version> <configuration> <url>jdbc:mysql://mysql-brood-base:3306/db_brood_raven_test?useUnicode=true&characterEncoding=UTF-8&useSSL=false</url> <user>xxx</user> <password>xxx</password> <driver>com.mysql.jdbc.Driver</driver> </configuration> </plugin>
对数据库进行maven操作的常用指令:
• clean : 清空database,比如上例中的db_brood_raven_test。 • baseline : 对于非空的database,需要先执行该指令创建基线。 • migrate : 根据当前数据库的flyway_schema_history表内容,对spring.flyway.locations中定义的目录下的脚本进行版本比较,执行尚未执行过的脚本。
5.注意事项
flyway并不能保证sql脚本的正确性,开源的flyway也没有提供回退功能。 如果你打了一个错误的sql到jar包里并部署,那么你很可能会得到一个错误版本的数据库,并需要手动恢复你的数据库! 这样你可能在下次上线新版本时,需要直接删掉flyway_schema_history表,让flyway重新做一个基线版本
工具二:footprint
1.背景介绍
存在两种管理情况: 1)想复用一组sql脚本而不是为拆分的微服务和集成的单片服务分别维护一组SQL脚本,能同时在微服务模式和单片集成服务模式下实现复用(flyway适用) 2)以微服务的形式分库部署时,集成到一个单片服务里去时,需要在一个database里分别按不同的业务空间来管理它们的版本 (flyway不适用,footprint 比flyway多出的功能就是支持一个database下多个业务空间的版本管控)
2.使用情况:
1)创建数据库版本控制表brood_db_version_ctl
CREATE TABLE IF NOT EXISTS `brood_db_version_ctl` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 数据库版本ID, `business_space` VARCHAR(50) NOT NULL COMMENT 业务空间, `major_version` INT NOT NULL COMMENT 主版本号, `minor_version` INT NOT NULL COMMENT 次版本号, `patch_version` INT NOT NULL COMMENT 补丁版本号, `version` VARCHAR(50) NOT NULL COMMENT 版本号,V[major].[minor].[patch], `custom_name` VARCHAR(50) NOT NULL DEFAULT none COMMENT 脚本自定义名称, `version_type` VARCHAR(10) NOT NULL COMMENT 版本类型:SQL/BaseLine, `script_file_name` VARCHAR(200) NOT NULL DEFAULT none COMMENT 脚本文件名, `script_digest_hex` VARCHAR(200) NOT NULL DEFAULT none COMMENT 脚本内容摘要(16进制), `success` TINYINT NOT NULL COMMENT 是否执行成功, `execution_time` INT NOT NULL COMMENT 脚本安装耗时, `install_time` VARCHAR(19) NOT NULL COMMENT 脚本安装时间,格式:[yyyy-MM-dd HH:mm:ss], `install_user` VARCHAR(100) NOT NULL COMMENT 脚本安装用户, PRIMARY KEY (`id`), UNIQUE INDEX `brood_db_version_ctl_unique01` (`business_space`, `major_version`, `minor_version`, `patch_version`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT = 数据库版本控制表 ;
2)sql脚本文件命名规约
[业务空间]_V[主版本号].[次版本号].[补丁版本号]_[脚本自定义名称].sql
方式二:通过自动化构建升级
工具:Liquibase
Liquibase 是一款专门用于数据库表结构版本控制的 CI/CD 工具
在源码构建过程中集成 Schema(数据库表结构) 版本管理 需要两个配置文件:
1)定义了数据库实例连接地址的配置文件 2)升级 Schema 所使用的 Sql 脚本文件
1.使用情况
通过 sql、yaml、xml、json 文件格式,开发人员需定义符合 Liquibase 风格的数据库表结构变更文件( changelog ) 代码目录结构展示:
. ├── Procfile ├── README.md ├── Schema │ ├── changelog.sql # 定义数据库表结构 │ └── mysql.properties # 定义数据库实例连接信息 ├── pom.xml └── src
mysql.properties 定义了数据库实例的连接方式,以及所引用的 changelog 文件地址
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://${ MYSQL_HOST}:${ MYSQL_PORT}/${ MYSQL_DATABASE}?createDatabaseIfNotExist=true&characterEncoding=utf8 username=${ MYSQL_USER} password=${ MYSQL_PASSWORD} changeLogFile=changelog.sql
changelog 文件示例:
-- liquibase formatted sql -- changeset guox.goodrain:1 create table person ( id int primary key, name varchar(50) not null, address1 varchar(50), address2 varchar(50), city varchar(30) ); -- rollback drop table person; -- changeset guox.goodrain:2 create table company ( id int primary key, name varchar(50) not null, address1 varchar(50), address2 varchar(50), city varchar(30) ); -- rollback drop table company;
2.Schema执行流程
A. 构建流程 执行正常的源码构建流程时,自动识别代码根目录下的 Schema 目录,准备 Schema 版本管理所需要的基础环境,包括 jre 和 Liquibase 工具包 B.启动流程 根据代码中定义好的配置文件,针对每一个数据库实例,进行自动升级处理
3. Spring boot中使用LiquiBase
A. 添加依赖
<dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>3.5.3</version> </dependency>
B. 添加配置 -application.properties配置方式
liquibase.change-log=classpath:config/liquibase/master.xml //存储变化的xml文件的位置 liquibase.user=sa //访问数据库的用户名 liquibase.password= //访问数据库的密码 liquibase.url=jdbc:h2:file:~/.h2/testdb //访问数据库的连接地址 liquibase.enabled=true //启用liquibase,Spring boot 2.0之后使用spring.liquibase.enabled liquibase.drop-first=false //默认为false,如果设置为true,liquibase将首先删除所有数据库对象的所有连接的用户。
-java配置方式
package com.aop8.config; import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import liquibase.integration.spring.SpringLiquibase; @Configuration public class LiquibaseConfig { @Bean public SpringLiquibase liquibase(DataSource dataSource) { SpringLiquibase liquibase = new SpringLiquibase(); liquibase.setDataSource(dataSource); liquibase.setChangeLog("classpath:config/liquibase/master.xml"); liquibase.setContexts("development,test,production"); liquibase.setShouldRun(true); return liquibase; } }
C. 配置DB change DB配置一般分为master配置和细节配置,master中使用include引入细节配置文件。 -添加master.xml 该文件被存放在src/main/resources 目录下 config/liquibase/master.xml
<?xml version="1.0" encoding="utf-8"?> <databaseChangeLog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd"> <include file="classpath:config/liquibase/changelog/201712022057_add_entity_Base.xml" relativeToChangelogFile="false"/> </databaseChangeLog>
使用TFS对数据库项目进行版本控制(有局限性)
1.创建数据库项目
• 在现有解决方案中,添加一个数据库项目 a) 在项属性中,将项目类型设置为“数据库项目”,SQL脚本文件选择“按架构”点击“下一步”, b) 设置数据库选项,此处选择排序规则为“Chinese_PRC_CI_AS”,点击“下一步”, c) 选中“导入现有架构”,并设置源数据库链接,选择已有的数据库, d) 在“配置生成/部署”中,选择部署操作为“创建部署脚本(.sql)并部署到数据库”(关键),并设置目标连接和数据库名称,因是对现有数据库的维护,此处设置与“导入现有架构”设置一致。 e) 点击“完成” 新建数据库项目,会根据现有数据库,将数据中所有对象定义全部生成到此项目中。 我们可以很方便的更改维护表、视图、存储过程、触发器。 将此项目签入到TFS上,就可以实现数据库项目的版本控制。
2.生成部署
a. 版本更改 通过CREATE语句,就可以完成存储过程的定义与更改。 数据库项目会自行判断数据库服务器上的存储过程版本与现有存储过程是否一样,如果不一样,会自动将更改更新到数据库服务器中。 表结构的更改可能会影响到现有数据库表中的数据,可能会将现有表删除再重新建表,数据当然也会被删除。
b. 将数据库项目部署到数据库服务器上 在此数据库项目上点右键,选择“部署”,前提是在第一步骤中选中“创建部署脚本(.sql)并部署到数据库”
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/database/291168.html