您当前的位置:首页 > 电脑百科 > 数据库 > 百科

云原生声明式数据库结构迁移工具 - SchemaHero

时间:2022-07-27 10:18:33  来源:  作者:江江111

SchemaHero 是一个开源的声明式数据库 schema 迁移的云原生工具,可将 schema 定义转换为可在任何环境中应用的迁移脚本。作为 CLI 工具和 Kube.NETes Operator 编写的 SchemaHero 消除了创建和管理与运行应用程序的所有环境兼容的顺序迁移脚本的任务。

云原生声明式数据库结构迁移工具 - SchemaHero

 

许多数据库 schema 管理工具创建了一个命令式接口,要求开发人员了解 schema 的当前状态以及将当前 schema(和相关数据)迁移到新的 schema 的相关命令, SchemaHero 提出了一个声明式接口的方式来替换穿透的命令式接口。

声明式模型

以声明式方式管理数据库 schema 有很多好处,包括:

  1. 遵守变更管理流程的能力
  2. 可重复部署到新环境
  3. 兼容新运行时

在声明式模型中,仅定义 schema 的当前状态,声明式 schema 管理程序会负责将 schema 从之前的任何状态迁移到所需状态所需的命令,只存储当前状态的好处是,在创建新的环境或者实例时,将不需要以前使用的数据库扩展、表等数据。

传统的数据库引擎通过被称为 DDL (数据定义语言)的 SQL 语句子集来接收 schema 变更。开发人员不需要为他们所针对的每个数据库引擎了解 DDL 之间的差别,根据数据库的能力和状态,从一个统一的声明式模型转换为适当的 DDL 命令可以通过编程方式进行处理。

当采用声明式模式来定义数据库 schema 管理时,就可以在应用之前根据一组策略来对 schema 进行验证。这对于只存储迁移脚本的命令式工具来说是不容易实现的。有了所需要的全部可用状态,就可以根据一组规则评估数据库 schema,以确保策略和最佳实践得以执行。

数据迁移

有两种类型的迁移需要管理和部署。

  1. Schema 迁移
  2. 数据迁移

Schema 迁移可以使用用 SQL 语法来表示,并改变数据库的结构。这些往往是一些新的表、列变更、更改索引数据等等。这些都是常用的写法,并且总是可以用幂等的语法来表达。不同的数据库引擎对如何应用这些规则执行不同的规则。例如,MySQL 不允许在事务中执行 schema 迁移,而 Postgres 是可以的。Schema 管理往往是数据库所独有的方式,而 SchemaHero 则专注于处理 schema 迁移。

不太常见的是,开发人员必须将一些数据迁移到数据库中的新格式。这可能涉及到计算一个新列并将其写入,或者在代码中创建新的值并将其插入它们。许多传统的数据库管理工具将 shema 迁移和数据迁移的任务融合到一个工具中去了。

SchemaHero 目前专注于 schema 迁移,并计划在未来支持数据迁移。

使用

接下来我们将来部署 SchemaHero 和一个示例数据库,将为一个虚拟的航空公司预订系统设计一个非常基本的数据库,并将其部署到 PostgreSQL 上去。

一开始我们将部署一个空数据库,创建一个初始 schema,然后修改该 schema,使其最终得到以下表结构:

云原生声明式数据库结构迁移工具 - SchemaHero

 

安装 SchemaHero

安装 kubectl 插件

SchemaHero 客户端组件被打包成了一个 kubectl 插件,并通过 krew 包管理器发布,所以首先我们需要先安装 krew,安装了 krew 过后,使用下面的命令即可安装 SchemaHero 客户端。

$ kubectl krew install schemahero

安装后可以通过下面的命令来校验是否安装成功。

$ kubectl schemahero version

正常你会看到安装的 SchemaHero 版本( 0.12.1 或类似版本)。

安装集群内组件

一旦安装了 kubectl 插件,我们就可以安装 SchemaHero 在 Kubernetes 集群中的组件了,只需要使用下面的命令即可一键安装:

$ kubectl schemahero install

该命令将创建一个名为 schemahero-system 的命名空间,并部署一个 SchemaHero operator ,可以通过执行以下命令来确认是否已经安装 SchemaHero :

$ kubectl get pods -n schemahero-system

正常情况下应该会看到 1 个 pod 正在运行,输出将类似于以下内容:

NAME           READY   STATUS    RESTARTS   AGE 
schemahero-0   1/1     Running   0          38s

客户端和集群组件都安装好过后,接下来我们可以去连接数据库。

连接数据库

接下来我们需要部署一个 PostgreSQL 实例,然后配置 SchemaHero 来管理该数据库实例。

为了方便,我这里直接将 PostgreSQL 的 Helm Chart 模板渲染后的 YAML 文件添加到 SchemaHero 代码仓库中去,这里我们部署到一个名为 schemahero-tutorial 的命名空间中去:

$ kubectl create ns schemahero-tutorial 
$ kubectl Apply -n schemahero-tutorial -f https://raw.Githubusercontent.com/schemahero/schemahero/mAIn/examples/tutorial/postgresql/postgresql-11.8.0.yaml

PostgreSQL 部署完成后,我们可以使用下面的命令连接到该数据库实例:

$ kubectl exec -it -n schemahero-tutorial 
  postgresql-0 -- psql -U airlinedb-user -d airlinedb

其中 airlinedb-user 的密码为 password 。

这里我们使用前面介绍过的 Beekeeper Studio 这个数据库管理工具来管理该数据库实例。

默认情况下上面我们部署的 PostgreSQL 实例无法在集群外访问,所以我们可以使用 kubectl 创建一个端口转发来暴露该数据库实例。

$ kubectl port-forward -n schemahero-tutorial svc/postgresql 5432:5432

然后我们就可以使用用户 airlinedb-user 、数据库 airlinedb 和密码 password 连接到数据库 127.0.0.01:5432 。

云原生声明式数据库结构迁移工具 - SchemaHero

 

连接后可以看到现在数据库还是空的。

云原生声明式数据库结构迁移工具 - SchemaHero

 

现在我们已经在集群中运行了 SchemaHero 和 PostgreSQL 实例,接下来我们可以向 SchemaHero 提供数据库信息,以便我们可以管理该数据库。我们可以通过使用连接信息将自定义资源部署到集群来实现。

database 对象可以允许 SchemaHero 管理数据库的 schema, database 中定义包括名称类型和连接参数。我们这里创建一个名为 airline-db.yaml 的文件,内容如下所示:

apiVersion: databases.schemahero.io/v1alpha4 
kind: Database 
metadata: 
  name: airlinedb 
  namespace: schemahero-tutorial 
spec: 
  connection: 
    postgres: 
      uri: 
        valueFrom: 
          secretKeyRef: 
            name: postgresql 
            key: uri

上面定义的 Database 就是 Schemahero 定义的一个 CRD 对象,这里我们是通过一个 secretKeyRef 引用前面 PostgreSQL 部署的一个身份验证数据,SchemaHero 支持从 inline、secrets 或 HashiCorp Vault 读取凭据。

直接应用上面的资源对象即可。

$ kubectl apply -f airline-db.yaml
$ kubectl get databases -n schemahero-tutorial 
NAME AGE 
airlinedb 47m

现在我们就可以通过 SchemaHero 来管理我们的 PostgreSQL 实例了,接下来我们使用 SchemaHero 将一个新表部署到这个实例中。

新建表

在这一步中,我们将把几个表部署到前面创建的 airlinesdb 数据库中去。在执行该操作时,我们将在 SchemaHero 中执行批准和拒绝工作流程,以了解如何在执行这些变更之前对其进行验证。

首先我们先定义一个简单的 airports 表,然后在我们的数据模型在定义路由时使用它。该表我们只定义了 2 列来表示机场代码和名称。

在使用 SchemaHero 之前我们可能会编写如下所示的 SQL 语句。

CREATE TABLE airport 
    ( code char(4) not null primary key, 
        name varchar(255) 
    )

而现在我们有了 SchemaHero 之后,就不需要编写 SQL 语句了,我们只需要创建为一个 SchemaHero 的 Table 自定义对象。

创建一个名为 airport-table.yaml 的资源清单文件,如下所示:

apiVersion: schemas.schemahero.io/v1alpha4 
kind: Table 
metadata: 
  name: airport 
  namespace: schemahero-tutorial 
spec: 
  database: airlinedb 
  name: airport 
  schema: 
    postgres: 
      primaryKey: [code] 
      columns: 
        - name: code 
          type: char(4) 
        - name: name 
          type: varchar(255) 
          constraints: 
            notNull: true

其中 spec.database 用来关联前面定义的 database 对象, spec.name 是 Postgres 数据库中真实的数据表名称,然后在 spec.schema 中定义表的结构, primaryKey 可以用来指定主键, columns 定义数据表的列定义。

同样直接应用该资源对象即可。

$ kubectl apply -f airport-table.yaml

需要注意的是尽管我们部署了 table 对象,但表结构并不会自动更改。相反,一个新的(或编辑的) table 对象将生成一个 migration 对象,可以检查然后批准或拒绝该变更。默认情况下, SchemaHero 需要审批流程,因为某些数据库结构迁移可能具有破坏性,可以通过向 database 对象添加属性来启用立即部署(未经批准)。

我们可以通过下面的命令查看到处于 pending 状态的迁移对象。

$ kubectl schemahero get migrations -n schemahero-tutorial
ID      DATABASE   TABLE     PLANNED EXECUTED APPROVED REJECTED 
eaa36ef airlinedb  airport   11s

如果没有找到资源,请等待几秒钟,然后重试,SchemaHero Operator 必须在 migration 可用之前完成 plan 阶段。

在批准该迁移之前,我们可以查看附加到 migration 对象上面生成的 SQL 语句。从上一个命令的输出中获取 ID,然后运行 describe migration 即可:

$ kubectl schemahero describe migration eaa36ef -n schemahero-tutorial

Migration Name: eaa36ef 

Generated DDL Statement (generated at 2020-06-06T10:41:04-07:00): 
  create table "airport" ("code" character (4), "name" character varying (255) not null, primary key ("code")); 

To apply this migration: 
  kubectl schemahero -n schemahero-tutorial approve migration eaa36ef 

To recalculate this migration against the current schema: 
  kubectl schemahero -n schemahero-tutorial recalculate migration eaa36ef 

To deny and cancel this migration: 
  kubectl schemahero -n schemahero-tutorial reject migration eaa36ef

在输出的顶部,生成的 DDL 语句是计划的迁移,这是 SchemaHero 将运行以应用此迁移的确切 SQL 语句。

在后面, SchemaHero 为后续步骤提供了 3 个命令:

  • apply :运行此命令将接受 SQL 语句, SchemaHero 将对数据库执行它。
  • recalculate SchemaHero SchemaHero
  • reject :运行此命令将拒绝迁移并且不执行它。

比如我们这里可以看到当前的迁移是安全的符合预期的,接下来我们可以批准迁移,以便让 SchemaHero 执行该计划,执行下面的命令即可:

$ kubectl schemahero -n schemahero-tutorial approve migration eaa36ef

Migration eaa36ef approved

我们可以再次运行 get migrations 来查看迁移的状态:

$ kubectl schemahero get migrations -n schemahero-tutorial
ID       DATABASE   TABLE    PLANNED  EXECUTED  APPROVED  REJECTED
eaa36ef  airlinedb  airport  9m38s    38s       52s

上面的信息表明迁移计划在 9 分 38 秒前,在 52 秒前批准,在 38 秒前执行。

现在我们在 Beekeeper Studio 工具中单击左侧导航中 Tables & Views 标题上的刷新按钮,正常我们现在可以在 public 下看到 airport 表,点开该表,可以看到表中的列数据。

云原生声明式数据库结构迁移工具 - SchemaHero

 

修改表

接下来我们来部署一个 table 对象然后来修改表结构。

和前面一样,首先我们创建一个 schedule 表,结构如下所示:

云原生声明式数据库结构迁移工具 - SchemaHero

 

定义一个对应的 Table 表对象,内容如下所示:

# schedule-table.yaml
apiVersion: schemas.schemahero.io/v1alpha4
kind: Table
metadata:
  name: schedule
  namespace: schemahero-tutorial
spec:
  database: airlinedb
  name: schedule
  schema:
    postgres:
      primaryKey: [flight_num]
      columns:
        - name: flight_num
          type: int
        - name: origin
          type: char(4)
          constraints:
            notNull: true
        - name: destination
          type: char(4)
          constraints:
            notNull: true
        - name: departure_time
          type: time
          constraints:
            notNull: true
        - name: arrival_time
          type: time
          constraints:
            notNull: true

直接应用上面的资源清单即可:

$ kubectl apply -f schedule-table.yaml -n schemahero-tutorial
$ kubectl schemahero get migrations -n schemahero-tutorial

当 schedule 迁移准备好时,它将显示在输出中:

ID      DATABASE  TABLE    PLANNED EXECUTED APPROVED REJECTED 
a9626a8 airlinedb schedule 21s 
eaa36ef airlinedb airport  4h      3h       3h

同样可以通过 describe 查看对应的 SQL 语句过后,如果是安全的,则可以审批该变更。

$ kubectl schemahero -n schemahero-tutorial approve migration a9626a8

批准后可以在 Beekeeper Studio 中查看是否有 schedule 表了。

云原生声明式数据库结构迁移工具 - SchemaHero

 

现在让我们对这个表结构做一些更改:

  • 使 departure_time 和 arrival_time 列可以为空
  • 添加一个名为 duration 的新列

修改上面的 schedule-table.yaml 文件,将 departure_time 和 arrival_time 列中的 constraints 属性移出掉,然后增加一个名为 duration ,类型为 int 且没有 constraints 属性。修改后的文件如下所示:

apiVersion: schemas.schemahero.io/v1alpha4
kind: Table
metadata:
  name: schedule
  namespace: schemahero-tutorial
spec:
  database: airlinedb
  name: schedule
  schema:
    postgres:
      primaryKey: [flight_num]
      columns:
        - name: flight_num
          type: int
        - name: origin
          type: char(4)
          constraints:
            notNull: true
        - name: destination
          type: char(4)
          constraints:
            notNull: true
        - name: departure_time
          type: time
        - name: arrival_time
          type: time
        - name: duration
          type: int

修改后重新应用该文件:

$ kubectl apply -f schedule-table.yaml

应用后,同样查看下该 migration 对象:

$ kubectl schemahero get migrations -n schemahero-tutorial
ID       DATABASE   TABLE     PLANNED  EXECUTED  APPROVED  REJECTED
a9626a8  airlinedb  schedule  9m30s    7m58s     8m0s
eaa36ef  airlinedb  airport   4h       4h        4h
fa32022  airlinedb  schedule  5s

可以看到多了一个新的 migration 对象处于 pending 状态。同样使用 describe 命令查看该 migration 的详细信息。

$ kubectl schemahero -n schemahero-tutorial describe migration fa32022

Migration Name: fa32022

Generated DDL Statement (generated at 2020-06-06T14:56:04-07:00):
  alter table "schedule" alter column "departure_time" type time, alter column "departure_time" drop not null;
  alter table "schedule" alter column "arrival_time" type time, alter column "arrival_time" drop not null;
  alter table "schedule" add column "duration" integer;

To apply this migration:
  kubectl schemahero -n schemahero-tutorial approve migration fa32022

To recalculate this migration against the current schema:
  kubectl schemahero -n schemahero-tutorial recalculate migration fa32022

To deny and cancel this migration:
  kubectl schemahero -n schemahero-tutorial  reject migration fa32022

上面的信息中可以看到该次迁移生成的 DDL 语句包括 3 个不同的语句, SchemaHero 将我们刚刚部署的 YAML 与实际的数据库结构进行了比较,并生成了上述命令。

同样校验下迁移语句没问题过后我们就可以直接批准该次迁移。

$ kubectl schemahero -n schemahero-tutorial approve migration fa32022
Migration fa32022 approved

正常批准后表结构就变更成功了。

到这里我们就基本上了解了 SchemaHero 的基础知识,当然 SchemaHero 还有需要功能没有介绍,可以查看官方文档
https://schemahero.io/docs/ 了解更多相关信息。

Git 仓库:
https://github.com/schemahero/schemahero

原文链接:
https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247502093&idx=1&sn=6475044141882963eabbfca39421f3ab



Tags:SchemaHero   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
云原生声明式数据库结构迁移工具 - SchemaHero
SchemaHero 是一个开源的声明式数据库 schema 迁移的云原生工具,可将 schema 定义转换为可在任何环境中应用的迁移脚本。作为 CLI 工具和 Kubernetes Operator 编写的 Schema...【详细内容】
2022-07-27  Search: SchemaHero  点击:(321)  评论:(0)  加入收藏
▌简易百科推荐
向量数据库落地实践
本文基于京东内部向量数据库vearch进行实践。Vearch 是对大规模深度学习向量进行高性能相似搜索的弹性分布式系统。详见: https://github.com/vearch/zh_docs/blob/v3.3.X/do...【详细内容】
2024-04-03  京东云开发者    Tags:向量数据库   点击:(9)  评论:(0)  加入收藏
原来 SQL 函数是可以内联的!
介绍在某些情况下,SQL 函数(即指定LANGUAGE SQL)会将其函数体内联到调用它的查询中,而不是直接调用。这可以带来显著的性能提升,因为函数体可以暴露给调用查询的规划器,从而规划器...【详细内容】
2024-04-03  红石PG  微信公众号  Tags:SQL 函数   点击:(7)  评论:(0)  加入收藏
如何正确选择NoSQL数据库
译者 | 陈峻审校 | 重楼Allied Market Research最近发布的一份报告指出,业界对于NoSQL数据库的需求正在持续上升。2022年,全球NoSQL市场的销售额已达73亿美元,预计到2032年将达...【详细内容】
2024-03-28    51CTO  Tags:NoSQL   点击:(19)  评论:(0)  加入收藏
为什么数据库连接池不采用 IO 多路复用?
这是一个非常好的问题。IO多路复用被视为是非常好的性能助力器。但是一般我们在使用DB时,还是经常性采用c3p0,tomcat connection pool等技术来与DB连接,哪怕整个程序已经变成以...【详细内容】
2024-03-27  dbaplus社群    Tags:数据库连接池   点击:(20)  评论:(0)  加入收藏
八个常见的数据可视化错误以及如何避免它们
在当今以数据驱动为主导的世界里,清晰且具有洞察力的数据可视化至关重要。然而,在创建数据可视化时很容易犯错误,这可能导致对数据的错误解读。本文将探讨一些常见的糟糕数据可...【详细内容】
2024-03-26  DeepHub IMBA  微信公众号  Tags:数据可视化   点击:(11)  评论:(0)  加入收藏
到底有没有必要分库分表,如何考量的
关于是否需要进行分库分表,可以根据以下考量因素来决定: 数据量和负载:如果数据量巨大且负载压力较大,单一库单一表可能无法满足性能需求,考虑分库分表。 数据增长:预估数据增长...【详细内容】
2024-03-20  码上遇见你  微信公众号  Tags:分库分表   点击:(17)  评论:(0)  加入收藏
在 SQL 中写了 in 和 not in,技术总监说要炒了我……
WHY?IN 和 NOT IN 是比较常用的关键字,为什么要尽量避免呢?1、效率低项目中遇到这么个情况:t1表 和 t2表 都是150w条数据,600M的样子,都不算大。但是这样一句查询 ↓select *...【详细内容】
2024-03-18  dbaplus社群    Tags:SQL   点击:(13)  评论:(0)  加入收藏
应对慢SQL的致胜法宝:7大实例剖析+优化原则
大促备战,最大的隐患项之一就是慢SQL,对于服务平稳运行带来的破坏性最大,也是日常工作中经常带来整个应用抖动的最大隐患,在日常开发中如何避免出现慢SQL,出现了慢SQL应该按照什...【详细内容】
2024-03-14  京东云开发者    Tags:慢SQL   点击:(13)  评论:(0)  加入收藏
过去一年,我看到了数据库领域的十大发展趋势
作者 | 朱洁策划 | 李冬梅过去一年,行业信心跌至冰点2022 年中,红衫的一篇《适应与忍耐》的报告,对公司经营提出了预警,让各个公司保持现金流,重整团队,想办法增加盈利。这篇报告...【详细内容】
2024-03-12    InfoQ  Tags:数据库   点击:(37)  评论:(0)  加入收藏
SQL优化的七个方法,你会哪个?
一、插入数据优化 普通插入:在平时我们执行insert语句的时候,可能都是一条一条数据插入进去的,就像下面这样。INSERT INTO `department` VALUES(1, '研发部(RD)', &#39...【详细内容】
2024-03-07  程序员恰恰  微信公众号  Tags:SQL优化   点击:(24)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条