首页 > 代码库 > 配置管理之数据库版本控制策略

配置管理之数据库版本控制策略

软件配置管理(Software Configuration Management,SCM)是界定软件的组成部分,对每个部分的变更进行版本控制,并维护不同部分之间的版本关联,以使软件在开发过程中任一时间的内容都可以被追溯的管理过程。软件配置管理通常包括版本控制、变更控制和过程支持三个大的方面,涉及配置项、工作空间管理、版本控制、变更控制、状态报告、配置审计等具体活动,软件配置管理一般会贯穿到整个软件研发生命周期以及各个知识领域,本文不做具体展开。

数据库版本是研发过程中需要把控的一个方面,但实际操作上很多时候并没有使用配置管理的思路进行统一管理,尤其是对研发管理尚未完善的团队而言更是如此。本文围绕配置管理这个主题,针对研发过程中的数据库版本控制策略展开讨论。从数据库版本这一概念入手,明确思路和目标并提供工作流程和实践模式。

一.关于数据库版本

关于配置管理下的数据库版本有三个主要概念:

1.      配置项

数据库相关的配置项包括所有数据库元素,如Model、DDL、DML以及各种配置文件,这些配置项都应该放到配置管理工具(常见的如SVN、Git)下进行统一管理。

2.      Change Set

Change Set就是数据库变更的最小单元,一个ChangeSet在物理表现上就是一个脚本文件。初始化后的数据库通过Change Set进行统一的更新,每个Change Set都应该有对应的回滚脚本,如果更新失败则使用该回回滚脚本进行回滚。

3.      Baseline

Baseline即基线,基线是数据库在特定时期的一个“快照”,为随后的工作提供一个标准和起点,通常根据功能发布范围建立数据库Baseline。

数据库版本控制通常没有像代码版本控制那样容易把控和管理,普遍也没有在研发团队中形成统一认识,导致在服务发布过程中只有对系统非常熟悉的开发人员通过手工尝试的方式进行数据库更新操作,一方面效率较低、容易出错;另一方面也不利于团队协作。这里我们还是要强调一下数据库版本控制的重要性,个人总结以下6点:

  • 信息透明跟踪:版本的作用就是提供统一视图,确保所有人都知道目前数据库处于哪个状态,方面信息的透明和跟踪
  • 尽早发现问题:有了数据库版本,开发人员在执行数据库更新操作时就能通过版本信息判断本次更新是否合理,避免在服务运行过程中才暴露问题
  • 降低出错概率:如果数据库版本信息能够一目了然,所有开发人员都能显式的在该版本信息的基础上进行下一步操作,而不是通过各种容易导致错误的隐式信息进行判断
  • 降低维护成本:数据库与代码不同,维护是一件很困难的事情,数据库版本信息为我们进行有效的数据库维护提供一个起点
  • 系统基线管理:根据配置管理思想,有了版本我们才能有基线,所以数据库版本为进行配置管理相关工作提供基础
  • 增量迭代演进:ChangeSet实际上就是一种增量思想,即通过每一次Change Set更新确保数据库满足一定的功能,从一个稳定状态到达下一个稳定状态

二.思路与目标

针对数据库版本控制的特点和重要性,我们的思路:

  • 开发部署分离:开发环境、测试环境和生产环境严格分离是进行数据库版本控制的第一步,通常生产环境与其他环境的分离没有问题,但也要确保开发环境和测试环境的分离。开发环境和测试环境分离是确保开发过程中的数据库版本控制能够在测试环境得到第一轮的校验,避免生产环境中出现问题
  • 版本可见:版本号在开发、测试和实施等步骤中确保所有人都能可见是执行数据库版本控制的基础
  • 版本一致:版本一致指要满足系统版本等式,如下:

  • 版本可回滚:当更新之后的最新版本有问题时,需要支持版本回滚到稳定版本
  • 版本可兼容:版本可兼容是一个扩展性功能,可以根据需要进行使用。版本可兼容的应用场景在于如果本次更新失败,则可以通过数据库版本不回滚、服务器版本回滚的方式确保系统正常运行,主要目的是想避免不必要的数据库回滚。具体做法上可以采用以下思路:同时存在服务器版本和数据库版本两个版本信息,一个数据库版本对应着一批有效服务器版本,如下:

发布时同时增加服务器版本和数据库版本;部署时如果服务器版本位于该数据库版本对应的合理服务器版本区间内(上图中的System002~System006),则该数据库版本可以不会滚,反之则必须回滚。

要满足上述思路和目标,我们需要设计数据库版本要素,包括:

  • 版本号:代表数据库当前版本的唯一编号
  • 版本校验:每次更新和回滚时,通过版本校验判断本次更新/回滚的目标版本是否就是当前的数据库版本,如果不是,则本次操作是无效的
  • 版本更新:版本校验成功之后进行数据库和版本的更新操作
  • 版本回滚:如果更新有问题,则通过版本回滚恢复数据库到上一个稳定状态
  • 版本基线:通过配置管理工具进行数据库的基线管理

同时,这里还有一个重要概念为Contraction scripts和Expansion scripts,前者是指数据库初始化时的脚本内容,后者是数据库初始化之后的所有递增性脚本内容。这样,每一个版本基线都可以看做是Contraction scripts,而每一个Change Set实际上就是Expansion scripts。

三.流程与实践

本节结合具体的操作模式和实践对数据库版本要素进行详细展开,并提供相关示例,后续sql语句仅供思路参考,非正式环境实例。

1.      版本号

我们通过创建版本表来存储和管理版本号,该版本表中包含:

  • 数据库版本:每次都更新
  • 最小服务器版本:不一定更新
  • 版本更新描述:本次更新的描述

创建版本表时同时初始化版本号,Mysql下的版本表创建过程如下:

CREATE TABLE `db_version` (
 `DATABASE_VERSION` varchar(30) NOT NULL,
 `MIN_SERVER_VERSION` varchar(30) NOT NULL,
 `UPDATE_DESCRIPTION` varchar(200) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
INSERTINTO `db_version` VALUES (MC-1.0.0-0001, MC-1.0.0-0001, '系统初始化');

通过版本表和版本可兼容原则,如果当前服务器版本 < 最小服务器版本,则服务部署失败。

2.      版本校验

版本校验比较本次更新的目标版本与数据库中当前版本是否一致,如果不一致则中断更新,抛出错误,Mysql下通过存储过程进行版本校验的脚本参考:

CREATE PROCEDURE MOBILECLINIC_CHECK_VERSION(P_PRE_VERSION VARCHAR(50))   
BEGIN
     DECLARE L_VER_NAME VARCHAR(30) ;
     DECLARE L_PRE_VERSION  VARCHAR(50);
     SET L_VER_NAME = 'MobileClinic';
     SELECT DATABASE_VERSION INTO L_PRE_VERSION FROM DB_VERSION WHERE NAME = L_VER_NAME;
     SELECT L_PRE_VERSION as '当前版本', P_PRE_VERSION as '目标版本';
          
     IF P_PRE_VERSION <> L_PRE_VERSION THEN
         select mysql_error();
     END IF;
END;
3.      版本更新
版本更新就是比对老版本号、更新新版本号和描述,并根据需要更新服务器最小版本号,如:
call MOBILECLINIC_CHECK_VERSION('MC-1.0.0-0002');

update DB_VERSION d set d.DATABASE_VERSION = 'MC-1.0.0-0003' , d.MIN_SERVER_VERSION = 'MC-1.0.0-0003' ,d.UPDATE_DESC = '新增表' ,d.UPDATE_TIME = SYSDATE() ;
4.      版本回滚

版本回滚就是比对新版本号,回滚老版本号、更新描述并回滚更新内容,如:

call MOBILECLINIC_CHECK_VERSION('MC-1.0.0-0003');

update DB_VERSION d set d.DATABASE_VERSION = 'MC-1.0.0-0002' , d.MIN_SERVER_VERSION = 'MC-1.0.0-0002' ,d.UPDATE_DESC = '更新回滚' ,d.UPDATE_TIME = SYSDATE() ;

--删除所更新的数据项--
alter table TEMP drop column XXX;

5.      版本基线

版本基线的管理策略如下,即通过一个可发布到版本递增到另一个可发布的版本:

6.      数据库版本控制的原则

数据库版本控制的原则总结如下:

  • 测试流程 = 发布流程
  • 按功能确定Baseline
  • Contraction script,采用增量式,包括creation(初始化ddl)、initialization(初始化dml)和cleanup(清空脚本)
  • Expansionscript,把Change Set作为提交测试和发布的最小单元
7.      数据库版本控制的工作流程

数据库版本控制的工作流程如下,各步骤参照字面意思即可:


8.      更新脚本(Change Set)定义

Change Set可采用以下方面进行定义:

  • 命名:CS_Baseline_YYYYMMDD_PatchNo.sql,例:CS_Tanggula2_20121223_01.sql
  • 步骤:更新目标数据库版本校验;DDL/DML更新;数据库(或最小服务器)版本更新

9.      回滚脚本(Roll Back)定义

Roll Back可采用以下方面进行定义:

  • 命名:RB_Baseline_YYYYMMDD_PatchNo.sql,例:RB_Tanggula2_20121223_01.sql
  • 步骤:回滚目标数据库版本校验、DDL/DML回滚、数据库(或最小服务器)版本回滚

10.      数据库版本控制与配置管理
在如SVN的配置管理工具中,配置项可以参考以下层级管理方式进行管理:


四.过程自动化

个人并不提倡数据库版本控制的过程自动化,因为自动化的东西有时候会不够灵活,而且数据库方面的自动化工具目前也还不是非常成熟,使用时要谨慎。目前市面上最好的数据库自动化工具应该是Liquibase(http://www.liquibase.org),支持多数据库、多格式ChangeSet和Roll Back。Liquibase通过使用格式化的SQL Change Set进行数据更新和回滚操作,官方示例如下:


同时,Liquibase也可以和maven进行无缝结合以进行构建生命周期的集成:

关于Liquibase本文不展开,大家可以根据需要进行尝试。

五.小结

配置管理的作用在于版本可跟踪、过程可重复和过程可自动化,数据库版本控制作为研发团队软件配置管理的一个组成部分也应该得到管理,本文对此提供了一些思路和方法供大家参考。

配置管理之数据库版本控制策略