首页 文章

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

提问于
浏览
44

Background

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

所有的表都是“如果不存在则创建”,并且所有SP等都被删除并重新创建 .

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

Question

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

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

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

我发现任何似乎都有我想要的答案的东西 . 与此类似,但不完全相同:

What are the best practices for database scripts under code control


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

感谢所有伟大的答案 - 都有他们的优点,所以我将采取最高票,但欢呼所有的投入 .

10 回答

  • 3

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

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

  • 2

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

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

  • 1

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

    这五个部分很重要,但基本上我们的想法是拥有一个基线,然后更改脚本(使用版本表) . 更新数据库意味着在当前版本“上方”应用更改脚本 . 而且这种策略非常适合VCS(没有冲突) .

  • 13

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

    它 Build 在.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");  
           }  
       }
    
  • 0

    如果你现在提前访问,那么大部分功能都在那里进行试用 . 你可以从http://www.red-gate.com/Products/SQL_Source_Control/index.htm下载 . 但是,它目前仅支持SVN和TFS . 你有没有标准化GIT?

    David(红门产品经理)

  • 4

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

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

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

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

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

  • 0

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

    • 添加每日(或部分构建)作业以将 DEV 数据库反向工程到目录结构中

    • 然后将它与存储库中的内容进行比较(通过简单的差异),基本上 FAIL 构建作业并报告 diff (如果有) . 这将表明DEV数据库的结构已更改,并且未反映在源代码管理中,

    • 将指示开发人员将更改添加到源控件(甚至使用报告的 .diff 文件)

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

    这样开发人员仍然可以按照常规方式工作:首先更改DEV数据库上的模式,并希望您在 flexibilityone truth 之间取得 balancer .

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

  • 21

    在工作中,我们大量使用一个强大的工具,它作为ActiveRecord的一部分(这是Rails web框架附带的默认ORM,名为Migrations .

    基本迁移如下所示:

    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使用和维护的简单性 .

  • 9

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

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

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

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

  • 2

    那里's a special tool for this exact thing. It'被称为Wizardby

    ...数据库持续集成和模式迁移框架

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

相关问题