持续集成和数据库管理

时间:2009-10-25 21:35:30

标签: database svn continuous-integration

当与其他几个人一起开展项目时,通常有几个人有不同的区域,例如数据库。

我的挑战是如何让多人在持续集成环境中编辑数据库模型。

开发人员建议编写一个“版本控制脚本”,其中每个编辑都输入到.sql脚本中,其中包含数据库能够检测到的版本号。模型的新增内容将在此文件中标记一个版本,并且一旦提交了脚本并运行了构建,数据库就会更新。

我也听说过发布者/订阅者......并仔细阅读了一下。

您如何在日常工作中管理这种情况,以及您可以给我什么建议让数据库更改尽可能无缝地运行?

**编辑**

已经提到了迁移框架和迁移脚本。如果您有一些实践经验并建议一个框架,那也将受到赞赏。

6 个答案:

答案 0 :(得分:21)

在杰出的Get Your Database Under Version Control帖子中引用杰夫阿特伍德:

  

...

     

我再次考虑这个问题   因为我的朋友和co-author K.   斯科特艾伦刚刚写了一篇辉煌   关于哲学和哲学的五部分系列   数据库版本控制的实践:

     
      
  1. Three rules for database work
  2.   
  3. The Baseline
  4.   
  5. Change Scripts
  6.   
  7. Views, Stored Procedures and the Like
  8.   
  9. Branching and Merging
  10.         

    ...

真的,即使很多人似乎对第3部分特别感兴趣,整个系列也值得一读。顺便说一下,看看第3部分提到的Bulletproof Sql Change Scripts Using INFORMATION_SCHEMA Views文章。您可能已经意识到这一点,但它解释了为什么编写idempotent更改脚本很重要。

关于工具,您可能需要查看UpToDater(以代码为中心),LiquiBase(基于xml)或... dbdeploy,稍微宝石基于ThoughtWorks中软件开发的实际经验。这不是第一个不好,但这个是我的首选(并且可用于Java,PHP或.NET)。

答案 1 :(得分:6)

我倾向于使用'migration'脚本运行得最好,这是从简单的版本化脚本开始的下一个阶段。通过迁移,您可以指定对数据库的更改(添加,删除等)以及如何撤消迁移所执行的更改。然后使用某种形式的版本对其进行标记,该版本不会与其他开发人员发生冲突。一个特别好的版本号是当前时间(以YYYYMMDDHHMMSS格式或从纪元开始的秒数)。这是一个不错的选择,因为你不太可能得到版本冲突,而且由于这些时间戳的严格增加性质,仍然很容易看到是否存在新版本。

注意:这很大程度上受Rails中迁移系统的影响。有关更多详情和想法,我强烈建议您查看该系统。

Rails迁移:

class CreateGroups < ActiveRecord::Migration
  def self.up
    create_table :groups do |t|
      t.string :name
      t.references :owner

      t.timestamps
    end
  end

  def self.down
    drop_table :groups
  end
end

学说迁移:

class CreateGroups extends Doctrine_Migration
{
    public function up()
    {
      // Create new author table
      $columns = array('id'   => array('type'          => 'integer',
                                       'length'        => 4,
                                       'autoincrement' => true),
                       'name' => array('type'          => 'string',
                                       'length'        => 255),
                       'owner_id' => array('type' => 'integer',
                                            'length' => 4));

    $this->createTable('groups', $columns, array('primary' => array('id')));
    }

    public function down()
    {
    $this->dropTable('groups');
    }
}

(抱歉教条中缺少时间戳...在rails中,timestamps调用会将created_at和updated_at字段添加到为您自动管理的表中。我不确定教条中的类似行为所以我将它们排除在外)。

答案 2 :(得分:1)

查看迁移框架。 AFAIK,这个想法来自rails,但是人们已经为这几乎所有其他东西构建了框架。

答案 3 :(得分:1)

取决于。

如果这是您正在讨论的已发布产品,则需要仔细跟踪架构编辑,以便您可以规划升级过程。现在开始考虑这个问题会很好,所以“版本控制脚本”会有一定的意义。但是向后/向前兼容性通常只是用户可见的要求,而不是“编译之间”要求。在发行版之间,维护升级脚本是有意义的,该脚本修改数据库表以将其引入新模式。

如果这是一个新的/未发布的产品,如果有人更改架构,您关心什么?为什么你甚至想要在持续集成构建之间保持数据库?无论如何,您应该能够使用自动化测试重新生成任何测试数据。但是,任何更改架构的人都应该更新测试。

对于已发布的产品,您可能希望拥有一组可以处理“1.0版”数据库的测试,以确保它可以成功升级到“1.1版”(例如)。

答案 4 :(得分:1)

问题中没有描述技术堆栈(包括使用的数据库),这与哪种解决方案最适合。

一种非常受欢迎的以Java为中心的迁移解决方案是FlywayDBUp非常相似,但侧重于.NET堆栈。

在Redgate,我们提供ReadyRoll,它与Visual Studio紧密集成,专门针对SQL Server。

答案 5 :(得分:0)

我们编写Subversion中的所有内容,并像其他任何代码一样将其检入项目中。所有数据库部署都是从源控制系统中提取的脚本完成的。如果两个人碰巧在同一个脚本上工作(这是相当罕见的),Subversion将允许你合并这两个脚本。