数据库的版本控制方案
1. 简介
作为软件开发工作的一部分对数据库进行建模是在项目的早期,但随着开发的进展,数据库模型会存在修改。在项目后期也可能由于客户提出的变更导致数据库模型的修改。许多看似不起眼的改动都可能给系统带来严重的后果。
我们希望有一种方法可以将数据库模型的修改和部署更新尽可能的平滑,把对系统可能的影响降到最低,并且即使发生问题也可以快速定位和修复,不造成毁灭的影响。
2. 数据库部署问题
软件开发中数据库的更改和部署有下面常见的一些问题。
- 数据库生产部署可能由团队外部的DBA完成,他们不熟悉我们开发的应用程序,也可能不了解数据库结构
- 手动部署容易出现人为错误
- 手动部署通常需要等到发版窗口时间
- 可能会向其他人提供不正确的脚本,从而导致部署错误的代码
- 数据库的多个副本存在于不同的开发人员计算机上,因此很难确定要使用和部署的正确版本
3.数据库源代码控制示例
假如我们有一个名为 dept 的表。这是创建它的脚本:
CREATE TABLE dept (
id NUMBER,
name VARCHAR(100)
);
我们会将此文件保存为 “dept.sql” 文件,将其添加到我们的存储库中,提交并将其推送到远程代码存储库。
如果想对数据库进行更改怎么办,例如我们增加一个 status 字段?这引出了一个我们该决定如何管理数据库代码的问题。
有两个方案,是基于状态的版本控制和基于迁移的版本控制。
- 方案一 基于状态
修改原有的 detp.sql 脚本。每当需要对表进行更改(例如添加状态列)时,它就会得到更新。
CREATE TABLE dept (
id NUMBER,
name VARCHAR(100),
status VARCHAR(20)
);
- 方案二 基于迁移
创建另一个新的脚本 customer_add_status.sql。一个脚本创建客户表,另一个脚本添加状态列。
ALTER TABLE dept ADD COLUMN status VARCHAR(20);
4. 基于状态 VS 基于迁移
基于状态和基于迁移是数据库版本控制的两种方法 。
基于状态:当存储反映数据库当前状态的数据库代码时,称为基于状态的版本控制。可以使用版本控制中的代码来创建数据库,脚本表示当前数据库定义是什么。
基于迁移:当存储反映为到达数据库当前状态而采取的步骤的数据库代码时,称为基于迁移的版本控制。版本控制中的脚本反映用于创建对象的原始脚本,以及后续所有变化的过程脚本。
基于状态的好处是
- 被认为更简单,因为只有一组脚本(例如,每个对象一个脚本,或一些其他划分)。
- 对象的定义在一个地方,所以任何人都可以打开它看看它应该是什么样子。
- 版本控制提交历史将告诉我们更改了什么、何时以及谁更改了它们。
基于迁移的好处是
- 数据库可以建立到某一时间点的状态,这有助于在有多个环境和分支的团队中使用
- 所有更改都在单独的脚本中,因此知道什么正在更改以及何时更改
- 由于脚本更小,部署可能更容易
数据库代码应该反映数据库的当前状态,还是应该反映为达到数据库的当前状态而采取的步骤呢?采用哪种方法需要与团队一起来讨论利弊。
通常的建议是使用基于迁移的部署,好处可能更多一些。这带来的另一个问题是可能会有大量过程脚本,当有大量过程脚本或者部署执行脚本带来大量的时间消耗的时候,我们可以用重新确定数据库脚本基线的方式来处理。