用版本控制工具将数据库版本化(转)

原文地址:http://blog.csdn.net/tywo45/article/details/2480078

1、概述

  版本化数据库的起点——创建一个数据库Schema基线,这个基线是一些数据库脚本(包括create table,alter table,drop table,insert data,update data,delete data等)。这些脚本可以位于同一.sql文件中,也可根据其它规划分别位于不同文件中,例如将视图脚本,初始化数据脚本,建表脚本分别置于不同的文件中。

2、版本化数据库过程

  数据库版本化与代码版本化的区别在于数据库中的生产数据是现场(即用户)创造的,当我们的表结构发生改变时,不能直接用drop table然后再create table,因为这样会导致生产数据丢失。而代码则完全由开发人员创造,可以用完全覆盖的方式升级。由于这点不同,致使数据库在版本化的过程中必然要采用与代码不同的方法。
  软件过程有一个过程方法叫迭代过程。对数据库的版本化,我觉得也可以采用这种类似的方法------后一个版本的脚本依赖于前一个版本的脚本,即当你要把数据库升级到第n个版本时,你必须先把数据库升级到第(n-1)个版本,以此递归。方法很简单,但实际的过程并不会太顺利,设想以下一个场景来描述一些常见的困难和问题。
  人力系统在V2.0.14版本时,有一张表叫demo_user,这张表有两个字段id和name,在我们进行V2.0.16版本的开发时,用户提出了要有cn_name(中文名)信息,并且这个信息不允许为空,如果为空,则必须用“无中文名”显示。这是个很简单的需求,我们只需要在demo_user表中添加一个cn_name字段即可------alter table demo_user add cn_name varchar2(64) not null;这个看似没有错误的语句,实际上是行不通的-----因为现场的这张表是有数据的,我们执行这条语句时会报下图所示的错误。
有经验的程序员可能想到了解决方法------将本来一条可以搞定的SQL分成三条,分别为:

alter table demo_user add cn_name varchar2(64) null;
update demo_user set cn_name = '无中文名';
alter table demo_user modify cn_name varchar2(64) not null;

  再设想,在V2.0.16版本时,日本有家公司要用我们公司的人力系统,我们的数据库如何直接从无到V2.0.16版本?
  很容易想到的一个方法是利用递归法,从第一个版本的脚本开始跑,一直跑到V2.0.16。如果我们中间经历了1000个版本,那就跑1000遍吧。实施的要哭了!面对重复性劳动时,人们都会抽象出一种比较好的方法来处理,就像设计模式中的状态模式代替无穷的if else语句一样,我们用各版本的全量脚本来代替增量脚本。这话不太好懂,以上面场景的demo_user表为例来说明一下吧。
以增量脚本的形式,我们会有三条SQL:

alter table demo_user add cn_name varchar2(64) null;
update demo_user set cn_name = '无中文名';
alter table demo_user modify cn_name varchar2(64) not null;

但以全量脚本的形式,我们只有一条SQL:

create table demo_user
(
ID VARCHAR2(18) not null,
NAME VARCHAR2(60) not null,
CN_NAME VARCHAR2(64) not null
);

  看到上面的全量和增量,有何感想?是不是觉得全量脚本只能用于新增局点,而已有局点,只能用增量脚本?是的,全量脚本就是给新增局点用的,但是目前,我觉得我们还不需要提供全量脚本------原因是,维护全量脚本给我们带来的实惠要远远少于我们的付出。
  再设想一个场景,日本局点不需要cn_name,他需要的是jp_name(日本名字)--------都说日本人bt,不过这个需求一点也不bt。如何做到呢?… …不累赘了,直接地说吧,此场景说明了,我们的脚本需要做到差异化控制,所以差异化控制功能必须纳入到控制范围,至于如何做到差异化控制?接着看吧!
  以上说得哆嗦了点,下面说说我们将数据库版本化后,在VSS(或其它版本控制软件工具)下的目录结构吧!见下图,相信图来得够直接了,俺就不哆嗦了:

                图2.1

3、问题列表

以项目的实际情况举例,其实各种情况都可以泛化的
1,  是否需要建一个oracle和sybase目录,以区分对待主业和实业。
答:这是个伪问题。我们同一个版本只会发往主业或实业中的一个,所以不存在用oracle和sybase这样的目录来区分。如果实业的改动和主业的改动一样,那么就分别在主业版本和实业版本都加上相应的脚本。
2,  开发要做哪些事?QA要做哪些事?实施要做哪些事?
答:
开发要做的
  1、提供数据库脚本,包括共用脚本和差异化脚本
  2、写好rs_build.sql
QA要做的
       1、发布新版本时,需要将上一版本的脚本复制到新版本的历史脚本中一并发布(参见图2.1)。
实施要做的
  1、修改rs_execute_sql.bat脚本(就是将用户名、密码和数据库名修改成相应的就可以了)
  2、双击execute.bat以执行脚本
  3、从.log文件中检查是否有错,如果发现错误,及时和开发人员沟通,然后由开发人员处理异常情况。

4、数据库版本管理产品

  • SQL Source Control
  • DBV数据库版本管理工具
  • Flyway
  • dbdeploy
  • liquibase

5、后记

  数据库版本化看似是个可有可无的过程,但做好了,可以减少开发和实施的许多事情,我们的系统就是个活生生的例子。之前在newland公司的时候,开发部门也没有数据库脚本控制,上个月听说那个部门已经接近解散了。本文所阐述的方法是来自以前在ht时的经验做法,但根据以前的一些问题作了些许改进。软件公司的发展都会经历从幼稚到成熟,借鉴其它公司的成功经验,提前认识并解决问题可减少损失。

posted @ 2017-07-23 08:57  每天进步一点点!!!  阅读(646)  评论(0编辑  收藏  举报