数据库结构和源代码控制 - 最佳实践

时间:2010-03-08 12:28:40

标签: database version-control

背景

我在一家公司工作了几年,其中所有数据库对象都存储在源代码管理中,每个对象一个文件。我们有一个列表,列出了添加新项目时维护的所有对象(允许我们按顺序运行脚本并处理依赖项)和一个运行创建一个大脚本以运行数据库的VB脚本。

所有表格都是“如果不存在则创建”,所有SP等都会丢弃并重新创建。

到目前为止,我现在正在一个数据库是主数据库并且没有数据库对象的源代码控制的地方工作,但我们确实使用redgate的工具来更新我们的生产数据库(SQL比较),这是非常的方便,只需要很少的工作。

问题

您如何处理数据库对象?我喜欢将它们置于源代码控制之下(并且,因为我们正在使用GIT,我希望能够处理脚本中的合并冲突,而不是数据库),但是我会被迫过去使用SQL比较的简易性来更新数据库。

我真的不想让我们在GIT中更新脚本,然后使用SQL compare从DEV DB更新生产数据库,因为我宁愿拥有'一个版本的真相',但我不知道我真的想重新编写一个自定义的软件来将所有脚本捆绑在一起。

我认为视觉工作室数据库版本可能会做类似的事情,但我不确定我们是否会有预算。

我确信这已经被要求死亡,但我找不到任何似乎有我想要的答案的东西。 与此类似,但不完全相同:

What are the best practices for database scripts under code control


开始赏金,因为我有兴趣拉票以获得更多意见 - 这里的答案是合理的,但我觉得应该有一个更简单的方法。

感谢所有伟大的答案 - 所有人都有自己的优点,所以我将获得最高票数,但欢呼所有投入。

10 个答案:

答案 0 :(得分:21)

看看这个关于数据库版本控制原理和实践的五部分系列文章(由K. Scott Allen撰写):

  1. Three rules for database work
  2. The Baseline
  3. Change Scripts
  4. Views, Stored Procedures and the Like
  5. Branching and Merging
  6. 这五个部分很重要,但基本上我们的想法是拥有一个基线,然后更改脚本(使用版本表)。更新数据库意味着在当前版本“上方”应用更改脚本。这个策略非常适合VCS(没有冲突)。

答案 1 :(得分:13)

我们使用Visual Studio Database Edition(DBPro)在源代码管理下拥有所有数据库对象。它是一个很棒的工具,版本控制我们的架构,构建,验证,允许代码分析,架构比较,部署,数据比较,重构等。它是从头开始设计的数据库管理和版本控制系统。强烈推荐。

这是DBPro首席架构师的博客网站: click here

答案 2 :(得分:9)

使用第三方SSMS加载项ApexSQL Source Control,如果您更喜欢使用本地存储库,则数据库对象可以自动编写脚本并推送到远程Git存储库,甚至推送到克隆的本地存储库。

ApexSQL Source Control支持开箱即用的Git源代码控制系统。这意味着您不需要安装任何其他Git客户端。除此之外,分支和合并是通过加载项UI集成和提供的。

答案 3 :(得分:4)

假设您使用.net框架,请查看Fluent Migrator以及讨论该项目的Hearding Code Podcast
我认为主要目的是使用数据库不可知方法,使用流畅的界面进行常规编码,轻松编写迁移代码。

它建立在.net框架之上。并使用多种数据库格式,包括SQL Server,SqlLite和MySQL。

这种方法的优点在于它与代码的其余部分一起使用,因此可以由SCM管理

示例:

   [Migration(1)]   
   public class CreateProjectsTable : Migration   
   {   
       public void Up()   
       {   
          Create.Table("Projects")              
            .WithIdColumn()             
            .WithColumn("Name").AsString().NotNullable()                
            .WithColumn("Position").AsInt32().NotNullable()             
            .WithColumn("Done").AsBoolean().NotNullable();
       }  
       public void Down()  
       {  
           Database.RemoveTable("Projects");  
       }  
   }

答案 4 :(得分:3)

如果您已经在使用Red Gate工具,则可以考虑使用SQL Source Control,它与SQL Compare和SQL Data Compare并行工作,以允许源控件中存在一个版本的事实。它目前处于早期访问状态,但大部分功能都在那里进行尝试。您可以从http://www.red-gate.com/Products/SQL_Source_Control/index.htm下载。但是,它目前仅支持SVN和TFS。你有没有标准化GIT?

David(红门产品经理)

答案 5 :(得分:2)

我们有一个系统,其中数据库名义上是我们的源代码控制系统中的主数据库,我们维护一系列“模式更改”脚本(.sql文件),每个脚本负责以幂等方式回滚更改然后应用它。每个脚本都只是编号,所以我们有000.sql(创建数据库并设置标准对象),001.sql等。

在开发期间,开发人员编写架构更改脚本并针对开发数据库运行它。每次更改都需要在dba.change_info表中添加一行,其中包含更改编号和简要说明。为了回滚更改,可以运行它的第一部分。对于SQL Server,回滚部分的幂等性是通过在发出DROP命令之前检查sysobjects等来处理的 - 类似于“drop ... if exist”结构。如果正在更改模型而不是简单地添加模型,则模式更改可能需要进行数据迁移,并且还用于维护参考数据。

在发布过程中,DBA(我们是一家小公司,因此这是其中一位开发人员所采取的角色)将发布的架构更改应用于生产数据库之间停止旧版本的应用程序并启动更新的应用程序。

这完全是一个手动过程,但满足了将数据从一个模型迁移到另一个模型的要求:将布尔标志扩展为一组选项,或将多对一关联转换为多对多关联。这通常不是使用简单的模式比较工具生成的东西。它还允许角色分离 - 尽管在实践中我们都可以完全访问生产,但是有足够的解耦,以便“DBA”可以读取和查看要在生产中应用的.sql文件。

理论上,至少可以通过简单地运行所有模式更改来构建完整的数据库(仅包含参考数据),以便从000.sql开始。在实践中,我们不会定期执行此操作,而是将生产数据库复制到dev,然后在发布之前运行回归测试之前应用更改脚本。这用于测试更改脚本本身,但仅适用于中等规模的生产数据库。

答案 6 :(得分:2)

我对RedGate工具包不太熟悉,但如果它与dbGhost类似,则必须有一个实用程序,允许您将数据库对象编写为每个对象一个文件的脚本。在这种情况下,我建议如下:

  • 添加每日(或部分构建)作业,将 DEV 数据库反向工程到目录结构中
  • 然后将它与存储库中的内容进行比较(通过简单的差异),基本上 FAIL 构建作业并报告diff(如果有)。这将表明DEV数据库的结构已更改,并且未反映在源控件中,
  • 将指示开发人员将更改添加到源代码管理中(甚至使用报告的.diff文件)

如果您有许多DEV数据库(每个用户或开发分支一个)并且它太麻烦,那么可能更好的组合就是在STAGE(发布前的TEST)版本的数据库上执行此类任务,此时您将PROD架构存储在存储库中,并且仅在预发布测试阶段从STAGE更新它,在此阶段您将确保您的架构更改也在存储库中。

这样开发人员仍可以通常的方式工作:首先更改DEV数据库中的架构,并希望您在所需的flexibilityone truth之间取得平衡。

在我的团队中,我们在更改DEV数据库后立即将更改添加到VCS,但我们仍然有这样的任务来比较不同数据库(DEV,STAGE和PROD)之间的模式。基本上,我们遵循我曾在How should you build your database from source control?中回答的内容。

答案 7 :(得分:1)

在工作中,我们大量使用强大的工具作为ActiveRecord的一部分(这是Rails网络框架Migrations附带的默认ORM。

基本迁移如下所示:

class AddSystems < ActiveRecord::Migration
  def self.up
    create_table :systems do |t|
      t.string  :name
      t.string  :label
      t.text    :value
      t.string  :type
      t.integer :position, :default => 1
      t.timestamps
    end
  end

  def self.down
    drop_table :systems
  end
end

为每个数据库更改创建了一个迁移,它们按时间戳按顺序创建。您可以运行预定义的方法以正确的顺序运行这些迁移,以便始终可以创建和/或回滚数据库。一些功能如下:

rake db:migrate #run all outstanding migrations
rake db:rollback #roll back the last run migration
rake db:seed #fill the database with your seed data

迁移具有创建表,删除表,更新表,添加索引等的方法。完整套件。迁移还会自动添加id列,t.timestamps部分会自动生成“created_at”字段和“updated_at”字段。

大多数语言都具有这些ORM功能,它们允许数据库维护在类似代码的状态,开发人员很容易理解,并且足够简单,DBA可以使用和维护。

答案 8 :(得分:0)

我目前在建模工具(DeZine for Databases)中维护数据库设计并将其存储在源代码管理下。在我的表设计中,我添加了一个包含两行的表,这些行具有模式和参考数据的版本号,每次更改/发布数据库时都会更新(用户不访问此表)。

参考数据在Excel电子表格(也在源代码管理下)中维护,该电子表格可以生成INSERT语句的SQL脚本以填充新数据库。

当需要新版本时,会发送架构脚本,参考数据脚本和安装程序包。安装程序包重命名旧数据库,从脚本创建新数据库并导入新的引用数据(可能也已更改)。然后将用户的数据从旧(重命名)数据库复制到新数据库。

这样做的好处是,当出现问题时,您可以恢复原始数据库,因为它尚未被修改。

答案 9 :(得分:0)

这是一个特殊的工具。它被称为Wizardby

  

...数据库持续集成&amp;架构迁移框架

Wizardby Workflow http://octalforty-wizardby.googlecode.com/svn/trunk/docs/img/database_versioning_with_wizardby.png