星辰.Net技术社区论坛

首页 » 数据库 » MSSQL » 数据库开发的持续集成 - Liquibase的简介和应用
star65225692 - 2008-6-20 15:33:00
Liquibase简介íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    Liquibase是一个用于跟踪、管理和应用数据库变化的开源的数据库重构工具。它将所有数据库的变化(包括结构和数据)都保存在XML文件中,便于版本控制。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    Liquibase具备如下特性:íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    * 不依赖于特定的数据库,目前支持包括Oracle/Sql Server/DB2/MySql/Sybase/PostgreSQL/Caché等12种数据库,这样在数据库的部署和升级环节可帮助应用系统支持多数据库。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    * 提供数据库比较功能,比较结果保存在XML中,基于该XML你可用Liquibase轻松部署或升级数据库。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    * 以XML存储数据库变化,其中以作者和ID唯一标识一个变化(ChangSet),支持数据库变化的合并,因此支持多开发人员同时工作。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    * 在数据库中保存数据库修改历史(DatabaseChangeHistory),在数据库升级时自动跳过已应用的变化(ChangSet)。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    * 提供变化应用的回滚功能,可按时间、数量或标签(tag)回滚已应用的变化。通过这种方式,开发人员可轻易的还原数据库在任何时间点的状态。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    * 可生成数据库修改文档(HTML格式)íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    * 提供数据重构的独立的IDE和Eclipse插件íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      Liquibase的核心就是存储变化的XML,如例:

<?xml version="1.0" encoding="UTF-8"?> íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
<databaseChangeLogíS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
 
xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.6"íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
  xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
  xsi:schemaLocation
="http://www.liquibase.org/xml/ns/dbchangelog/1.6íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.6.xsd"
>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
   
<changeSet id="1" author="bob">íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
       
<createTable tableName="department">íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
           
<column name="id" type="int">íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
               
<constraints primaryKey="true" nullable="false"/>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
           
</column>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
           
<column name="name" type="varchar(50)">íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
               
<constraints nullable="false"/>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
           
</column>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
           
<column name="active" type="boolean" defaultValue="1"/>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
       
</createTable>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
   
</changeSet> íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
</databaseChangeLog>

íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi

íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi

      其中,changeSet包含不同的数据库变化,几乎涵盖了所有的数据库变化类型,具体支持的类型要看API,我这里给几个例子:íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      *  创建和删除表、视图、存储过程、主键、外键、索引等íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      *  重命名表、视图、列等íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      *  加入列缺省值、唯一约束、非空约束等íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      *  合并两个列íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      *  在一个表的数据的基础上创建一个字典表íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      除此之外,Liquibase还允许你运行自己的Sql脚本、执行Shell程序。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      之所以所说”几乎涵盖“,是因为目前我发现不支持用户自定义数据和自定义函数的。由于在我新的数据库开发原则中摒弃了对他们的依赖,所以也不痛苦。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
Liquibase在持续集成中的应用íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      如果你基于Java开发,你可能会更喜欢Liquibase,如果基于Ruby On Rails开发,你可能会选择Migration 和 Rake。我基于.Net,考察过Red Gate($),Migration.Net, Machine.Migrations,Power Tools等等,最终还是选择了Liquibase。如何整合到我的开发流程中来,我选择命令行以及基于命令行的MsBuild任务。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      用命令行搞一个bat文件执行Liquibase,用户数据库部署(见我例子中的deploy.bat)。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      Msbuild提供比较、部署、文档生成等等全套功能,用于开发的全过程,当然也用于CC.Net(见例子中的ci.proj)。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      具体的应用包括:íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      * 开发人员在本地完成一个阶段的开发后,使用ci.proj中的diff target比较本地数据和基线数据,产生changelog.xml,提交到SVN(这里,XML文件中的changeSet中的Author取开发人员本地机器的用户名)íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      * CC.Net检测到SVN的变化,触发持续集成过程,调用ci.proj中的deploy在一个测试数据库中创建最新的数据结构,然后对实体类和访问层进行测试(开发人员在本地机器的测试亦如此)。测试成功,使用ci.proj中的doc生成文档,发布在持续集成服务器的IIS中。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      * 如果是trunk项目则在测试完成后需要在SVN上打Tag,然后使用ci.proj中的publish发布数据库部署升级程序(含changelog.xml)íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      * 发布的数据库部署升级程序中含deploy.bat给部署人员用以部署或升级现有的产品系统数据库。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      关于changelog.xml的合并:íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      * 每一次开发人员有新的changelog.xml提交,我会通过SVN的Merge功能将其新的changeSet合并íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      * 这个过程可以通过SVN自动完成,但鉴于数据库的变化影响面太大,需要谨慎审核,因此还是选择手工来做íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
    íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      关于test.proj: 这是用MsBuild写的一个测试案例,测试ci.proj提供的数据库比较和升级功能。      íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      关于ci.proj的说明:íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      * 对dtproperties的特殊处理íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
        一旦你使用过Sql Server的企业管理器操作过数据库,会自动生成这个表存一些数据库对象的属性。虽然在企业管理器中显示为系统表,但它的object_id很大,使得liquibase将其看做用户表,会影响数据库比较结果,因此在ci.proj中会检查参与比较的两个数据是否存在该表,如果不存在则创建它。íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
      * <Target Name="CheckExec">íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
        MsBuild使用Java命令行调用liquibase,如果执行出错,MsBuild不能得到该错误,这样将导致CC.Net的持续集成在失败时报成功。没有找到更好的办法,我将执行Java得到的输出写入exec.log文件,然后用CheckExec检查其中是否有Failed关键字。可能还有其他的关键字需要检查,如果园友发现还请告诉我。
íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi

<Target Name="CheckExec">íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
   
<ReadLinesFromFile File="$(ExecLog)">íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
       
<Output TaskParameter="Lines" PropertyName="ExecOutput"/>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
   
</ReadLinesFromFile>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
   
<Message Text="$(ExecOutput)" Importance="high"/>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
   
<StringComparison Comparison="Contains" Param1="$(ExecOutput)" Param2="Failed">íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
       
<Output TaskParameter="Result" PropertyName="StringSearchResult"/>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
   
</StringComparison>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
   
<Delete Files="$(ExecLog)"/>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
   
<Error Text="liquibase report error" Condition="$(StringSearchResult)"/>íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi
</Target>

íS ¾ £Hª;www.netcsharp.cnÅÑà’­×AŰi

附件: db-ci-deploy.zip
1
查看完整版本: 数据库开发的持续集成 - Liquibase的简介和应用