为什么要进行数据库版本控制?
现代软件工程逐渐向持续集成、持续交付演进,软件一次性交付了事的场景逐渐无法满足复杂多变的业务需求,“如何高效地进行软件版本控制”成为我们面临的挑战。同时,软件也不是仅仅部署到某一套环境中,而是需要部署到开发、测试、生产以及更多的客户环境中,“如何一套代码适应不同的环境”也成为我们要思考的问题。
一套软件的副本要部署在不同的环境(图源:Flyway)
代码版本管理工具(Git、SVN 等)和托管平台(Github、Erda DevOps Platform 等)让我们能有效地进行代码版本管理。越来越丰富的 CI/CD 工具让我们能定义可重复的构建和持续集成流程,发布和部署变得简单清晰。
“基础设施即代码”的思想,让我们可以用代码定义基础设施,从而抹平了各个环境的差异。
可以说,在软件侧我们应对这些挑战已经得心应手。
但是绝大多数项目都至少包含两个重要部分:业务软件,以及业务软件所使用的数据库——许多项目数据库侧的版本控制仍面临乱局:
- 很多项目的数据库版本控制仍依赖于“人肉维护”,需要开发者手动执行 SQL;
- 环境一多,几乎没人搞得清某个环境上数据库是什么状态了;
- database migrations 脚本没有统一管理,遗失错漏时有发生;
- 不确定脚本的状态是否应用,也许在这个环境应用了但在另个环境却没有应用;
- 脚本里有一行破坏性代码,执行了后将一个表字段删除了,数据无法恢复,只能“从删库到跑路”;
- ……
为了应对这样的乱局,我们需要数据库版本控制工具。
数据库版本控制,即 Database Migration,它能帮你:
- 管理数据库的定义和迁移历程
- 在任意时刻和环境从头创建数据库至指定的版本
- 以确定性的、安全的方式执行迁移
- 清楚任意环境数据库处于什么状态
从而让数据库与软件的版本管理同步起来,软件版本始终能对应正确的数据库版本,同时提高安全性、降低维护成本。
Erda 如何实践数据库版本控制
Erda 是基于多云架构的一站式企业数字化平台,为企业提供 DevOps、微服务治理、多云管理以及快数据管理等云厂商无绑定的 IT 服务。Erda 既可以私有化交付,也提供了 SaaS 化云平台 Erda Cloud,以及开源的社区版。
当你正在阅读这篇文章时,有无数来自不同组织的应用程序正在 Erda Cloud 或 Erda 私有化平台的流水线上完成以构建和部署为核心的 CI/CD 流程,无数的代码,以这种持续而自动化的方式转化成服务实例。
Erda 平台不但接管了这些组织的应用程序的集成、交付,Erda 项目自身的集成也是托管在 Erda DevOps 平台的。Erda 自身的持续集成和丰富的交付场景要求它能进行安全、高效、可持续的数据库版本控制,托管在 Erda 上的应用程序也要求 Erda 提供一套完整的数据库版本控制方案。
Erda 项目使用 Erda MySQL Migrator 作为数据库版本控制工具,它被广泛应用于 CI/CD 流程和命令行工具中。
基本原理
第一次使用 Erda MySQL Migrator 进行数据库版本控制时会在数据库中新建一个名为 schema_migration_history 的表,如下如所示:
schema_migration_history 表的基本结构(部分主要字段)
Erda MySQL Migrator 每次执行 database migration 时,会对比文件系统中的 migrations 脚本和 schema_migration_history 表中的执行记录,标记出增量的部分。在一系列审查后,Erda MySQL Migrator 将增量的部分应用到目标 database 中。成功应用的脚本被记录在案。
Erda MySQL Migrator 命令行工具
erda-cli 工具的构建与安装
erda-cli
是 erda 项目命令行工具,它集成了 Erda 平台安装、Erda 拓展管理以及开发脚手架。其中 erda-cli migrate
命令集成了数据库版本控制全部功能。
从 erda 仓库 拉取代码到本地,切换到 master 分支,执行以下命令可以编译erda-cli :
% make prepare-cli
% make cli
注意编译前应确保当前环境已安装 docker。编译成功后项目目录下生成了一个 bin/erda-cli
可执行文件。
使用 erda-cli migrate 进行数据库版本迁移
Erda MySQL Migrator 要求按 modules/scripts