数据库部署策略(SQL Server)

时间:2009-02-02 21:09:10

标签: c# asp.net sql-server-2005 svn visual-studio-2005

我正在寻找一种方法来进行日常部署并使数据库脚本与发布保持一致。

目前,我们有一个相当不错的部署源代码的方式,我们有单位代码覆盖,持续集成和回滚程序。

问题是保持数据库脚本与发布一致。每个人似乎都尝试在测试数据库上运行脚本,然后在实时运行它们,当ORM映射更新(即更改生效)时,它会选择新列。

第一个问题是没有任何脚本可以写在任何地方,通常每个人都“尝试”将它们放入Subversion文件夹,但是一些懒惰的人只是在现场运行脚本而且大部分时间都没有人知道谁对数据库做了什么。

第二个问题是我们有4个测试数据库,它们总是脱节,真正排列它们的唯一方法是从实时数据库进行恢复。

我非常相信,这样的流程需要简单,直接且易于使用,以帮助开发人员,而不是阻碍他们。

我正在寻找的技术/想法使开发人员想要记录他们的数据库脚本很容易,因此他们可以作为发布过程的一部分运行。 开发人员希望关注的流程

任何故事,用例甚至链接都会有所帮助。

15 个答案:

答案 0 :(得分:32)

对于这个问题,我选择使用迁移工具:Migratordotnet

通过迁移(在任何工具中),您可以使用一个简单的类来执行更改并撤消它们。这是一个例子:

[Migration(62)]
public class _62_add_date_created_column : Migration
{
    public void Up()
    {
       //add it nullable
       Database.AddColumn("Customers", new Column("DateCreated", DateTime) );

       //seed it with data
       Database.Execute("update Customers set DateCreated = getdate()");

       //add not-null constraint
       Database.AddNotNullConstraint("Customers", "DateCreated");
    }

    public void Down()
    {
       Database.RemoveColumn("Customers", "DateCreated");
    }
}

此示例显示如何处理易失性更新,例如向具有现有数据的表添加新的非空列。这可以轻松实现自动化,您可以轻松地在不同版本之间上下移动。

这对我们的构建非常有价值,并且简化了流程非常

我在这里发布了.NET中各种迁移框架的比较:http://benscheirman.com/2008/06/net-database-migration-tool-roundup

答案 1 :(得分:7)

阅读K.Scott Allen's series of posts on database versioning
我们构建了一个基于他描述的技术以受控方式应用数据库脚本的工具,它运行良好 然后,这可以用作持续集成过程的一部分,每个测试数据库在对保留数据库升级脚本的URL进行提交时都会对其进行更改。我建议使用基线脚本和升级脚本,以便您始终可以运行一系列脚本,以将数据库从其当前版本获取到所需的新状态 这仍然需要开发人员的一些过程和纪律(所有更改都需要转换为新版本的基本安装脚本和补丁脚本)。

答案 2 :(得分:6)

我们几年来一直在使用RedGate的SQL Compare:

http://www.red-gate.com/products/index.htm

专业版有一个命令行界面,您可以使用它来设置部署过程。

答案 3 :(得分:5)

我们使用K. Scott Allen描述的数据库版本控制的修改版本。我们使用Database Publishing Wizard创建原始基线脚本。然后是一个基于SQL SMO的自定义C#工具来转储存储过程,视图和用户功能。包含架构和数据更改的更改脚本由Red Gate工具生成。所以我们最终得到像

这样的结构
Database\
    ObjectScripts\ - contains stored procs, views and user funcs 1-per file
    \baseline.sql - database snapshot which includes tables and data
    \sc.01.00.0001.sql - incremental change scripts
    \sc.01.00.0002.sql
    \sc.01.00.0003.sql

自定义工具会根据需要创建数据库,必要时应用baseline.sql,必要时添加SchemaChanges表,并根据SchemaChanges表中的内容根据需要应用更改脚本。每次我们通过cc.net进行部署构建时,该过程都会作为nant构建脚本的一部分发生。

如果有人想要使用schemachanger应用程序的源代码,我可以将它放在codeplex / google或任何地方。

答案 4 :(得分:4)

转到此处:

https://blog.codinghorror.com/get-your-database-under-version-control/

向下滚动到odetocode.com网站的5个链接列表。神奇的五部曲系列。我会以此为出发点来获取想法并找出适合您团队的流程。

答案 5 :(得分:4)

如果您正在讨论尝试保持数据库模式同步,请尝试使用Red Gate SQL Comparison SDK。基于创建脚本(newDb)构建临时数据库 - 这就是您希望数据库的外观。将newDb与旧数据库(oldDb)进行比较。从该比较中获取更改集并使用Red Gate应用它。您可以将此升级过程构建到测试中,并且可以尝试让所有开发人员同意有一个地方可以保留数据库的创建脚本。这种做法适用于跨多个版本升级数据库以及在每个步骤之间运行数据迁移脚本和流程(使用XML文档映射创建和数据迁移脚本)

编辑:使用Red Gate技术,您只关心创建脚本,而不是升级脚本,因为Red Gate提供了升级脚本。它还允许您删除并创建索引,存储过程,函数等。

答案 6 :(得分:2)

您应该考虑使用像MSBuild或NAnt这样的构建工具。我们使用CruiseControl.NET,NAnt和SourceGear Fortress的组合来处理我们的部署,包括SQL对象。 NAnt db build任务调用sqlcmd.exe,以便在检查Fortress后更新我们的开发和登台环境中的脚本。

答案 7 :(得分:1)

我们使用Visual Studio for Database Professionals和TFS来版本和管理我们的数据库部署。这允许我们像代码一样对待我们的数据库(签出,签入,锁定,查看版本历史,分支,构建,部署,测试等),如果我们愿意,甚至可以将它们包含在相同的解决方案文件中。

我们的开发人员可以在本地数据库上工作,以避免在共享环境中踩到彼此的变化。当他们将数据库更改检查到TFS时,我们会持续集成以构建,测试和部署到我们的集成开发环境。我们在发布分支上有单独的构建,以便为每个后续环境创建差异部署脚本。

稍后,如果在发行版中发现错误,我们可以转到发布分支并同时修补代码和数据库。

这是一款出色的产品,但由于微软的营销失误,它的采用在早期受到阻碍。它最初是Team System下的一个单独产品。这意味着为了同时使用开发人员版和数据库版的功能,您需要升级到更昂贵的Team Suite版本。我们(和许多其他客户)对此感到悲痛,我们非常高兴他们今年宣布DB Pro has been folded into the developer edition,并且任何获得开发者版许可的人都可以安装数据库版本。

答案 8 :(得分:1)

Gus断然提到DB Ghost(上图) - 我将其作为潜在的解决方案。

我的公司如何使用DB Ghost的简要概述:

  • 在初始开发期间合理解决了新数据库的模式之后,我们使用DB Ghost'Data和Schema Scripter'为所有数据库对象(以及任何静态数据)创建脚本(.sql)文件,我们将这些脚本文件签入到源代码管理中(该工具将对象分成诸如“存储过程”,“表格”等文件夹)。此时,我们可以使用DB GHost'Packager'或'Packager Plus'工具创建独立的可执行文件,以便从这些脚本创建新的数据库。
  • 通过签入特定脚本文件来检入对数据库模式的所有更改。
  • 我们可以随时使用打包程序创建可执行文件,以便(a)创建新数据库或(b)更新现有数据库。某些与路径相关的更改(例如,需要更新数据的更改)需要进行一些自定义,但我们有运行的更新前和更新后脚本。

“更新”过程涉及创建干净的“源”数据库,然后(在更新自定义脚本之后),源DB与目标数据库的模式之间的比较。 DB Ghost更新目标数据库以匹配

我们经常对生产数据库进行更改(我们在7个不同的生产环境中有14个客户)但不可避免地使用DB Ghost更新可执行文件(在我们的构建过程中创建)部署了足够大的更改集。未签入源(或未签入到正在发布的相应分支中)的任何生产更改都会丢失。这迫使每个人一直在检查变更。

总结:

  • 如果您强制执行使用DB Ghost更新可执行文件部署所有数据库更新的策略,则可以“强制”开发人员始终检查其更改,无论它们是否在过渡期间手动部署。
  • 在构建过程中添加一个步骤(或多个步骤)以创建DB Ghost更新可执行文件将实际执行测试以验证是否可以从脚本创建DB(即,因为DB Ghost创建了'源'DB,即使在创建更新可执行程序包时,如果添加一个步骤(或多个步骤)来执行更新包[在您提到的四个测试数据库中的任何一个上],您可以使测试数据库与源保持一致。

使用此工具(实际上是一套相关工具)可以“轻松”部署哪些更改有一些警告和一些限制,但它们都相当轻微(至少对我的公司而言):

  • 必须在其中一个自定义脚本中重命名对象
  • 整个数据库始终更新(例如,单个模式中的对象无法单独更新),因此难以在主应用程序数据库中支持客户特定对象

答案 9 :(得分:0)

这些帖子中有很多链接我都想跟进(几年前我“推出了自己的系统”,必须看看是否有相似之处)。你需要的一件事,就是我希望在这些环节中提到的,就是纪律。如果任何人都可以随时更改任何内容,我不太清楚任何自动化系统是如何工作的。 (你的问题暗示这可能发生在你的生产系统上,但显然不可能是真的。)

让一个人(传说中的“数据库管理员”)专门负责管理数据库,特别是生产数据库的更改,这是一个非常常见的解决方案。至于维护X开发和测试数据库的一致性:如果它/它们被许多用户使用,那么最好通过让个人充当变更的“结算所”来获得最佳服务;如果每个人都有自己的数据库实例,那么他们就有责任保持秩序,并且当他们需要刷新的基线数据库时,拥有一个集中的数据库“源”将是至关重要的。

以下是最近可能感兴趣的Stack Overflow帖子:how-to-refresh-a-test-instance-of-sql-server-with-production-data-without-using

答案 10 :(得分:0)

本书Refactoring Databases在概念层面解决了许多这些问题。

就工具而言,我知道DB Ghost适用于SQL Server。我听说Visual Studio的Data Dude版本在最新版本中确实得到了改进,但我对它没有任何经验。

就真正推动持续集成风格的数据库开发而言,由于您需要的数据库副本数量很多,因此它可以非常快速地获得资源。当数据库可以放在开发人员工作站上时非常可行,但是当数据库太大而需要跨网格部署时,这是不切实际的。要做到这一点,你每个开发人员需要1个数据库副本[进行DDL更改的开发人员,而不仅仅是对procs的更改] + 6个常用副本。常用副本如下:

  1. INT DEV - >开发人员“检入”他们对INT DEV的重构以进行集成测试。集成测试通过后,此数据库将复制到DEV。
  2. DEV - >这是数据库的“官方”开发副本。 INT DEV定期刷新DEV副本。致力于新重构的开发人员从DEV获得数据库的新副本。
  3. INT QA - >除了QA团队之外,与INT DEV相同的想法。当集成测试在此处传递时,此数据库将复制到QA和DEV *。
  4. QA
  5. INT PROD - >与INT QA相同的想法,除了生产。当集成测试在此处传递时,此数据库将复制到PROD,QA *和DEV *
  6. PROD
  7. *在DEV / QA / PROD行中复制数据库时,您还需要运行脚本来更新与特定环境相关的测试数据(例如,在质量保证中设置QA团队用来测试的用户,但不是存在于生产中)。

答案 11 :(得分:0)

一种可能的解决方案是研究在测试数据库上实施DML审核,然后将这些审核日志滚动到脚本中进行最终测试和实时部署。 SQL Server 2008显着改进了DML审计,但即使SQL Server 2005也通过触发器支持它。

答案 12 :(得分:0)

Red Gate有一篇论文描述了如何实现构建自动化:http://downloads.red-gate.com/HelpPDF/ContinuousIntegrationForDatabasesUsingRedGateSQLTools.pdf

这是围绕SQL Source Control构建的,它与SSMS和您现有的源代码管理系统集成。

答案 13 :(得分:0)

我编写了一个基于.NET的工具来自动处理数据库版本控制。我们一直在生产中使用这个工具来处理向多个环境推出数据库更新(包括补丁),在每个数据库中记录运行了哪些脚本,并以自动方式完成所有操作。它有一个命令行控制台,因此您可以创建使用此工具的批处理脚本。看看:https://github.com/bmontgomery/DatabaseVersioning

答案 14 :(得分:0)

对于它的价值,这是我前雇主使用的简单,低成本方法的一个真实例子(我试图给我现在的雇主留下深刻的印象,作为基本的第一步)。

添加一个名为“DB_VERSION”的表格或类似表格。在每个升级脚本中,向该表添加一行,其中包含您认为适合描述升级的尽可能少的列,但至少我会建议{VERSION,EXECUTION_DATE,DESCRIPTION,EXECUTION_USER}。现在你有一个具体的记录,一直在发生什么。如果有人运行他们自己的未经授权的脚本,您仍然需要遵循上述答案的建议,但这只是一种显着改进现有版本控制的简单方法(即没有)。

现在让我们有一个从数据库的v2.1到v2.2的升级脚本,你想要验证那个孤独的特立独行的人真的在他的数据库上运行它,你可以只搜索VERSION ='v2的行。 2'如果得到结果,请不要运行此升级脚本。如有必要,可以内置到控制台实用程序应用程序中。