查看原文
其他

解读|Bytebase 如何实现对 MySQL 库表同步的支持

zp Bytebase 2022-12-19

什么是库表同步?

在传统的场景里,如果想使两个数据库的 Schema 一致,需要人工使用工具获得两个数据库的 Schema,观察它们之间的差别,写出对应的 DDL 语句并执行。而库表同步自动地获取数据库 Schema、计算差异、生成 DDL 语句,然后人工审核通过即可自动执行。

概述

Bytebase  v1.8.0 上线了对 MySQL 库表同步的支持,这个功能在 Bytebase 实现机制如下图所示:
首先通过 Bytebase 的 dump 模块获得两个数据库 (DB1、DB2) 的 Schema,然后传递给 Schema Diff 引擎获得 diff 结果的 DDL 语句,最后利用 Bytebase 的工作流来执行这一系列 DDL 语句,最终 DB1 和 DB2 的结构将保持一致。

Schema Diff 引擎

SQL AST

Bytebase 的 dump 模块可以获得数据库的 Schema,然后通过 Parser 将他们转换成 AST (抽象语法树)。
例如,CREATE TABLE `person`(id INT, name VARCHAR(25)) 的 AST 结构类似下面这样:

在 SQL AST 上计算 Diff

Bytebase 可以通过遍历 AST 拿到数据库对象的各个属性,将对应的对象放在一起比较就可以计算出如何从一个对象变更到另一个对象。将计算出来的 Diff 转换成 AST,再将 AST 还原成 SQL 语句,一个对象的 diff 就完成了。
一个简单的例子,如下图所示:在比较两份 Schema 的时候,通过遍历 AST 可以发现左边的 Schema 比起右边的 Schema 多了一个 name 列,少了一个 age 列。Bytebase 要做的就是将 age 列加上并将 name 列删去,如图中的 Diff AST 所示。

处理依赖关系

数据库对象和操作内都可能存在着依赖关系,Bytebase 需要正确地处理这些依赖关系。

不同数据库对象之间的依赖关系

Bytebase 需要通过拓扑排序的顺序来处理数据库对象之间的依赖,下列对象的创建顺序需要是由上到下的,而删除顺序是从下到上的:

  1. Table

  2. Column

  3. View

  4. Index

  5. Constraint

而在创建 function,procedure,trigger 这三个对象的时候, MySQL 不会对它们做验证,所以删除原有(如果有)对象之后,可以在任意位置创建它们。

不同数据库操作之间的依赖关系

除了数据库对象之间有依赖关系,不同的操作类型之间也有依赖关系,上面提到的先删除再新增一个同名对象就是一个简单的例子。

Bytebase 将操作类型作以下排序:

  1. 创建此前不存在的新的对象,例如新增一个原本不存在的列 A。

  2. 原地修改属性,例如修改列的默认值,我们不需要先删除列再增添列,只需要原地修改即可。

  3. 删除无法原地修改属性的对象,例如 Index,如果两个同名 Index 的定义不一致,MySQL 不允许我们修改 Index 的定义。Bytebase 将会删除这个 Index,并在随后的第四条重建。

  4. 重建无法原地修改属性的对象。

  5. 删除多余的对象。

将 AST 还原成 SQL 语句

通过上面的顺序将 diff 结果排序后,我们就获得了一系列 AST,通过解析器将这些 AST 还原成 SQL 语句就得到了我们最终的结果。

tl;dr

  1. 将 SQL 语句转换成 AST。

  2. 比较对应的 AST 并生成对应的 Diff 结果(以 AST 的形式表示)。

  3. 调整 Diff 结果的顺序。

  4. 将 Diff 结果 AST 还原成 DDL 语句。


使用 Schema Sync

可以参考 Synchronize Schema 文档了解如何使用 Bytebase 完成 MySQL 库表同步:https://www.bytebase.com/docs/change-database/synchronize-schema。

通过飞书审批 Bytebase 工单
Bytebase 助力 TiDB Workshop Day @上海
工程团队如何合理地管理数据库访问
0 门槛 5 分钟体验 Bytebase 库表同步

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存