Skip to content

数据库初始化

我们知道,代码可以通过版本管理工具来进行管理。那 sql 呢,同样也是可以的。但为什么要这么做呢,因为我们在项目或产品开发过程中,很难再一开始就把业务理清楚,把数据库表设计好,因此数据表也会在开发周期中不断迭代。尤其是对于已上线的应用来说,这个版本新增了多少字段,或是修改了多少条数据,如果这些数据没有去存档,等到上线时,测试反馈 bug 时,我们查日志才发现原来是漏了某个字段未发布等等似曾相识的问题。那我们怎么去规避呢?

flyway 介绍

flyway 是一款开源的数据库版本管理工具。它可以很方便的在命令行中使用,或者在 Java 应用程序中引入,用于管理我们的数据库版本。 那通过它我们怎么有效的来规避这些问题呢?

标品里怎么做的

打开标品项目模块,里面有个 sql 文件夹,有以下文件:

  • generator.sql 代码生成器 sql,如果不用可忽略,手动执行
  • V2.3.0__create_table.sql 标品业务 2.3 sql
  • V2.4.0__create_table.sql 标品业务 2.4 sql
  • V99.0.0__init_data.sql 标品业务初始数据 sql

这个命名有什么规则吗?有的。Vx.x.x__xx.sql 形如这种格式。非这种格式的将会被忽略。

flyway 会根据版本号递增去执行脚本,执行成功会生成flyway_schema_history表。其中的 version 字段记录的便是 Vx.x.x 值。

多次执行脚本不会重复执行,他的依据是文件内容 md5,也就是你如果改动了某个版本 sql,但同时与存档的文件内容 md5 比对不正确后,将会报错。

那我们应该如何去调整呢?两种方式:

  • 删除flyway_schema_history表里最新一条版本号执行记录,然后再修改对应版本 sql,再重新执行
  • 重新递增一个版本号,书写最新的内容,用于调整之前的问题

再开发阶段,比较推荐第一种。后续进入业务周期迭代时,比较推荐第二种。

好了,这样做了,有什么好处?

有什么好处

  • 关于数据库的任何改动我们都有 sql 文件记录,好处不用多说
  • sql 文件执行自备自动化能力,这个对于部署来说简直不要太友好

标品里是如何落地的

在 framework-generator 模块 util 文件夹下有个DbMigrateUtil,打开看下核心代码:

java

/**
 * 数据库迁移。
 *
 * @author mjyang
 * @date 2023/7/26 18:04
 */
public class DbMigrateUtil {
    public static void main(String[] args) {
        // 配置 host,dbName,user,password 运行便会自动执行 sql 文件下 V 打头的 sql 文件。
        String host = "xx.xx.xx.xx:xx";
        String dbName = "xx_test";
        String url = "jdbc:mysql://" + host + "/" + dbName + "?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=true&serverTimezone=Asia/Shanghai";
        String user = "root";
        String password = "123456";
        Flyway flyway = Flyway
                .configure()
                .locations("filesystem:sql")
                .ignorePendingMigrations(true)
                .dataSource(url, user, password)
                .target(MigrationVersion.LATEST)
                .baselineOnMigrate(true)
                .validateOnMigrate(true)
                .load();
        flyway.validate();
        flyway.migrate();
    }
}

核心代码也就是这么几行。修改对应的数据库参数,运行起来,便会发现,它自动帮我们创建好了数据库。

写在最后

但是你会发现,为什么这里的手动运行和前面说的自动化运行不一样呢?这是因为考虑到多人协作下,如果开发人员不固定的情况下,人员频繁更换,且开发习惯如果没有调整到文件先行的话,这个自动化运行可能会带来副作用。想一下,我通过 navicat 直接修改不是更快吗?因此选择了手动运行的方式。那它的价值又是什么呢?它的最大价值便是在于提供标准化的 sql 版本管理,让我们更加专业,版本上线更稳。