维基百科对模式迁移的定义是(强调是我的)。
...是指对关系数据库模式的增量、可逆变化和版本控制的管理。每当有必要将数据库的模式更新或恢复到某个较新或较旧的版本时,就会对该数据库进行模式迁移。
......以及数据库重构的相关定义为。
...对数据库模式的简单改变,在保留其行为和信息语义的同时改进其设计
当构建软件产品时,使用控制版本系统的部分想法是提高所有在项目上工作的团队成员之间的协作,这肯定包括检查用于构建最终客户使用的实际工件的代码及其依赖关系,但也包括该最终产品恰好需要的一切。
通常,我们构建的产品需要一个数据存储,大多数情况下,这个数据存储恰好是一个关系型数据库。跟踪该数据存储的演变是很重要的,特别是在演变实时环境的时候,以确定新的变化是否会破坏现有的数据。
一般来说,无论用什么语言编程,数据库模式迁移工具都有两种风格。
- 基于DSL的:有某种伪语言来定义用于与数据库引擎交互的指令;和
- 明确的SQL:用字面上的SQL语句来定义所需的指令。
对于Go来说,以下是一些可用的具体选择。
- 建立你自己的 😄
- golang-migrate/migrate。CLI+包(显式SQL)。
- github.com/go-pg/migra…。包(显式SQL)。
- github.com/jackc/tern:CLI (Explicit SQL),
- github.com/gobuffalo/p…:CLI(DSL+显式SQL),以及
- 还有更多......
我个人最喜欢的是golang-migrate/migrate ,因为它支持各种数据输入(migrate 称之为源),这里只提几个。
在你的输入不被支持的情况下,可以选择实现你自己的输入,以及大多数流行的数据库引擎,例如。
因为这一系列不同的来源和数据库,我建议你在安装migrate ,因为默认情况下它会安装所有的数据库,也许这是你不想要的,因为它给你的项目带来了你不需要的依赖,例如,对于只用Filesystem和PostgreSQL构建migrate ,你需要类似的东西。
go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate
运行migrate -h 应该指出支持的源码和数据库驱动,在上面的例子中,它打印出来了。
Source drivers: file
Database drivers: postgres, postgresql, stub
最佳实践、惯例和指南
选择一个处理迁移的工具是难题的一部分,另一部分是定义最佳实践、惯例和准则,以便在处理数据库模式迁移时遵循。
-
定义文件名惯例
支持创建迁移的工具,比如
migrate,为这些生成的文件提供了一个默认的格式,在migrate,默认情况下,文件的前缀是工具被调用的时间戳;它还支持按顺序使用文件。 -
倾向于使用SQL而不是DSL
使用DSL而不是显式SQL至少有两个好处:允许没有很多SQL经验的工程师快速对数据库模式迁移文件进行修改,以及避免数据库引擎锁定。根据我的经验,学习SQL和使用显式语句是一种更好的时间投资,因为它可以让你准确地了解在迁移文件中执行的是什么指令。
-
实际的迁移应该是部署管道的一部分,与提及这些变化的代码同时部署。
这样做的目的是为了对可能出现的故障做出快速反应,如果我们在数据库模式变化之前部署代码变化,那么当代码涉及到表的非现有变化时,就会出现错误,如果我们在不同的步骤中部署迁移,也会出现类似的情况。我们应该努力将数据库迁移起来,然后在同一步骤中应用新的代码,这是管道的一部分,这样的话,如果迁移失败,旨在使用这些变化的代码也将不会被部署。
总结
数据库模式迁移可以帮助你维护对数据库所做的修改,尽管Go生态系统中有很多工具可用,但棘手的部分不是选择其中之一,而是在使这些修改生效时找到完美的平衡,以及在应对迁移错误时需要遵循的步骤。