5.4 使用 Flyway 管理生产环境中的数据库

记录任何数据库更改是很好的做法,就像您通过版本控制管理应用程序源代码一样。您需要一种确定性和自动化的方式来推断数据库的状态、是否已应用特定更改、如何从头重新创建数据库以及如何以可控、可重复和可靠的方式迁移它。持续交付方法鼓励尽可能自动化,包括数据库管理。

在 Java 生态系统中,最常用的跟踪、版本控制和部署数据库更改的两个工具是 Flyway(https://flywaydb.org)和 Liquibase(https://liquibase.org)。它们都与 Spring Boot 完全集成。本节将展示如何使用 Flyway。

5.4.1 理解 Flyway:数据库的版本控制

Flyway 是一个为数据库提供版本控制的工具。它为数据库状态的版本提供单一真相来源,并增量跟踪任何更改。它自动化更改,让您可以重现或回滚数据库的状态。Flyway 高度可靠,在集群环境中安全使用,并支持多种关系型数据库,包括 Amazon RDS、Azure Database 和 Google Cloud SQL 等云数据库。

注意:本节将介绍 Flyway 提供的一些功能,但建议您查阅官方文档以发现此工具提供的所有强大功能(https://flywaydb.org)。

Flyway 的核心是管理数据库更改。任何数据库更改都称为迁移,迁移可以是版本化的或可重复的。版本化迁移由唯一版本号标识,按顺序恰好应用一次。对于每个常规版本化迁移,您还可以提供可选的撤消迁移以恢复其效果(以防出现问题)。它们可用于创建、更改或删除关系对象(如模式、表、列和序列)或更正数据。另一方面,可重复迁移在其校验和更改时每次都会应用。它们可用于创建或更新视图、存储过程和包。

两种类型的迁移都可以在标准 SQL 脚本(适用于 DDL 更改)或 Java 类(适用于 DML 更改,如数据迁移)中定义。Flyway 通过在首次运行时自动在数据库中创建的 flyway_schema_history 表来跟踪哪些迁移已应用。您可以将迁移想象为 Git 仓库中的提交,模式历史表包含随时间应用的所有提交列表(图 5.6)。

图 5.6 Flyway 迁移表示数据库更改,可以想象为 Git 仓库中的提交。

注意:使用 Flyway 的前提是您要管理的数据库和具有正确访问权限的用户都存在。一旦有了数据库和用户,Flyway 就可以为您管理数据库更改。您不应该使用 Flyway 来管理用户。

您可以使用独立模式或将 Flyway 嵌入 Java 应用程序中。Spring Boot 为其提供自动配置,使将 Flyway 包含在应用程序中非常方便。与 Spring Boot 集成时,Flyway 将在 src/main/resources/db/migration 文件夹中搜索 SQL 迁移,在 src/main/java/db/migration 中搜索 Java 迁移。

运行模式和数据迁移是第 2 章介绍的 15 要素方法论描述的管理过程之一。在这种情况下,采用的策略是将其嵌入应用程序本身。默认情况下,它在应用程序启动阶段激活。

打开 Catalog Service 项目,在 build.gradle 文件中添加 Flyway 依赖。添加后记得刷新或重新导入 Gradle 依赖。

代码清单 5.20 在 Catalog Service 中添加 Flyway 依赖

dependencies {
 ...
 implementation 'org.flywaydb:flyway-core'
}

5.4.2 使用 Flyway 初始化数据库模式

您将应用的第一个数据库更改通常是初始化模式。到目前为止,我们一直依赖 Spring Boot 提供的内置数据源初始化功能,并提供包含要运行的 SQL 语句的 schema.sql 文件。现在我们可以使用 SQL Flyway 迁移来初始化模式。

首先,删除 schema.sql 文件并从 Catalog Service 项目的 application.yml 文件中删除 spring.sql.init.mode 属性。

接下来,创建 src/main/resources/db/migration 文件夹。这是 Flyway 默认搜索 SQL 迁移的地方。在文件夹内,创建 V1__Initial_schema.sql 文件,其中包含初始化 Catalog Service 应用程序所需的数据库模式的 SQL 语句。确保在版本号后输入两个下划线。

Flyway 期望 SQL 迁移文件遵循特定的命名模式。常规版本化迁移应遵循以下结构:

  • 前缀 — V(版本化迁移)
  • 版本 — 使用点或下划线分隔为多个部分的版本号(例如 2.0.1)
  • 分隔符 — 两个下划线:__
  • 描述 — 用下划线分隔的单词
  • 后缀 — .sql

在 V1__Initial_schema.sql 迁移脚本中,您可以包含创建 book 表的 SQL 指令,Spring Boot JDBC 将其映射到 Book 持久化实体。

代码清单 5.21 用于模式初始化的 Flyway 迁移脚本

CREATE TABLE book (
 id BIGSERIAL PRIMARY KEY NOT NULL,
 author varchar(255) NOT NULL,
 isbn varchar(255) UNIQUE NOT NULL,
 price float8 NOT NULL,
 title varchar(255) NOT NULL,
 created_date timestamp NOT NULL,
 last_modified_date timestamp NOT NULL,
 version integer NOT NULL
);

当您让 Flyway 管理数据库模式的更改时,您将获得版本控制的所有好处。现在您可以按照第 5.1.2 节提供的说明启动新的 PostgreSQL 容器(如果之前的容器仍在运行,使用 docker rm -fv polar-postgres 移除),运行应用程序(./gradlew bootRun),并验证一切正常工作。

注意:在本书附带的仓库中,您可以找到直接查询 PostgreSQL 数据库和验证 Flyway 生成的模式和数据的有用命令(Chapter05/05-end/catalog-service/README.md)。

您的自动化测试也将使用 Flyway。继续运行它们;它们应该全部成功。完成后,将更改推送到远程 Git 仓库,并从 GitHub Actions 检查提交阶段结果。它们也应该成功。最后,停止应用程序执行(Ctrl-C)和 PostgreSQL 容器(docker rm -fv polar-postgres)。

5.4.3 使用 Flyway 演进数据库

随着应用程序的发展,数据库模式也需要演进。Flyway 使这个过程变得简单且可靠。

假设您需要向 book 表添加一个新字段来存储图书的描述。创建一个新的迁移文件 V2__Add_description_column.sql:

代码清单 5.22 添加新列的 Flyway 迁移脚本

ALTER TABLE book ADD COLUMN description varchar(2000);

当应用程序启动时,Flyway 将检测到新的迁移文件并自动应用它。flyway_schema_history 表将记录此迁移已应用,确保它不会再次运行。

Flyway 的优势在于:

  • 版本控制 — 每个更改都被跟踪和版本化
  • 可重复 — 迁移可以在任何环境中以相同的方式运行
  • 可回滚 — 如果出现问题,可以创建撤消迁移
  • 团队协作 — 多个开发人员可以安全地处理数据库更改

通过使用 Flyway,您确保数据库模式与应用程序代码一起版本化,使部署更可靠且更易于管理。

results matching ""

    No results matching ""