数据库部署策略(SQL Server)

问题描述:

我正在寻找一种方法来执行日常部署并使数据库脚本与版本保持一致。目前,我们有一个相当不错的部署源代码的方式,我们有单元代码覆盖,持续集成和回滚过程。数据库部署策略(SQL Server)

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

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

第二个问题是,我们有4个测试数据库,它们总是不符合要求,真正为它们备份的唯一方法是从活动数据库进行恢复。

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

我在寻找的是技术/想法,它使开发人员很容易记录他们的数据库脚本,使他们可以作为发布过程的一部分运行。 开发人员需要遵循的过程

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

+0

另请参阅http://stackoverflow.com/questions/468703/source-control-and-stored-procedures – 2009-09-10 09:29:33

+0

“开发人员希望遵循的流程”不是解决目标的唯一方法:您可以锁定他们对共享实例的访问权限,让他们编写单元测试,并让他们编写自动化系统将执行和验证的脚本。不太敏捷,会非常痛苦,并且取决于你是多么严厉,这可能会导致这个过程的士气下降/叛变/颠覆。但这是解决问题的另一种方法。您可以通过让他们在自己的盒子上而不是共享实例上进行数据库更改来减轻一些痛苦。 – 2011-11-06 00:55:27

对于这个问题,我选择使用迁移工具: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

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

您应该考虑使用构建工具,如MSBuild或NAnt。我们使用CruiseControl.NET,NAnt和SourceGear Fortress的组合来处理我们的部署,包括SQL对象。 NAnt数据库构建任务调用sqlcmd.exe,在我们的开发和临时环境中检入Fortress后更新脚本。

+0

我会看看这个。但是,我不想使用SourceGear类型系统。我喜欢在签入时在TEST数据库上运行脚本的想法。如果用户检查7个脚本,它会如何处理排序?只是一个通用的规则,所有的所有依赖脚本需要结合? – cgreeno 2009-02-05 12:15:21

+0

堡垒并非特别需要;这只是我们使用的VCS。你可以使用Subversion或CVS甚至SourceSafe。就排序而言,您可以在NAnt构建脚本中进行设置。 – 2009-02-05 15:04:59

去这里:

http://www.codinghorror.com/blog/archives/001050.html

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

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

编辑:使用Red Gate技术,您只能关心创建脚本,而不是升级脚本,因为Red Gate会提供升级脚本。它也将让你退学,并创建索引,存储过程,函数等

+0

我以前用过这个,它是一个很好的工具。这不是我正在寻找的。我更多地寻找一种将发行版绑定到一系列SQL语句的方法。 – cgreeno 2009-02-05 12:05:30

我们使用SQL从展鹏现在比较好几年了:

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

Pro版本有命令行界面,您可能可以使用它来设置您的部署过程。

+0

雅我以前也使用过它,它是一个很好的工具,但不是我正在寻找的。 – cgreeno 2009-02-05 12:06:07

我们使用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或任何地方。

在这些帖子中有很多链接,我想跟进(我在多年前“推出了自己的”系统,必须查看是否有相似之处)。有一件事你需要,而且我希望在这些链接中提到,是纪律。我不太清楚任何时候任何人都可以改变任何东西,任何自动化系统都可以工作。 (您的问题意味着这可能发生在您的生产系统上,但显然这不可能是真实的。)

让一个人(数据库管理员)致力于管理对数据库的更改,尤其是生产数据库,是一个非常常见的解决方案至于保持X开发和测试数据库的一致性:如果它/他们被许多用户使用,再一次最好的办法是让个人充当变化的“信息中心”;如果每个人都有他们自己的数据库实例,那么他们有责任保持它的秩序,并且当他们需要刷新的基线数据库时,具有中央一致性数据库“源”将是至关重要的。

这里是最近的堆栈溢出后,可能会感兴趣:how-to-refresh-a-test-instance-of-sql-server-with-production-data-without-using

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

至于工具去,我知道DB Ghost适用于SQL Server。我听说在最新版本中,Data Dude版本的Visual Studio已经真正得到了印证,但我没有任何经验。由于您需要的数据库副本数量很大,因此真正实现持续集成方式数据库开发的速度非常快。当数据库适合开发人员工作站时,这是非常可行的,但当数据库非常庞大以至于需要跨网格部署时,这是不切实际的。要做到这一点,你需要每个开发人员1个数据库副本[进行DDL更改的开发人员,而不仅仅是过程更改] + 6个常见副本。常见副本如下:

  1. INT DEV - >开发人员“检入”他们的重构到INT DEV进行集成测试。集成测试通过后,该数据库将被复制到DEV。
  2. DEV - >这是数据库的“官方”开发副本。 INT DEV定期刷新DEV的副本。从事新重构的开发人员从DEV获取数据库的全新副本。
  3. INT QA - >除了质量保证小组外,与INT DEV相同。当集成测试通过此处时,此数据库将被复制到QA和DEV *。
  4. QA
  5. INT PROD - >除生产外,与INT QA相同。当集成测试经过此地,此数据库复制到PROD,QA *和DEV *
  6. PROD

*当跨DEV/QA/PROD线复制数据库,您还需要运行脚本更新与特定环境相关的测试数据(例如,设置QA团队用于测试但在生产中不存在的QA中的用户)。

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

我们的开发人员可以在本地数据库上工作,以避免在共享环境中彼此更改。当他们检查到TFS的数据库更改时,我们持续集成以构建,测试和部署到我们的集成开发环境。我们在发布分支上有单独的版本,为每个后续环境创建差异部署脚本。后来,如果在发行版中发现错误,我们可以转到发布分支并同时修复代码和数据库。

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

一个可能的解决方案是考虑在您的测试数据库上实施DML审计,然后将这些审计日志转换为脚本以进行最终测试和实时部署。 SQL Server 2008在DML审计方面显着改进,但即使SQL Server 2005也通过触发器支持它。

Gus一手提到DB Ghost(上图) - 我把它作为潜在的解决方案。

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

  • 架构一个新的DB之后最初的发展过程中得到合理的解决,我们使用DB鬼“数据和架构的编剧”创建所有数据库对象(以及任何静态数据)的脚本(.sql)文件,并将这些脚本文件签入到源代码控制中(该工具将这些对象分隔为诸如“存储过程”,“表格”等文件夹) 。此时,我们可以使用DB GHost的'Packager'或'Packager Plus'工具创建一个独立的可执行文件,从这些脚本创建一个新的数据库。
  • 对数据库模式的所有更改都通过签入到特定脚本文件的源代码签入。
  • 在任何时候,我们都可以使用打包器创建可执行文件,以便(a)创建新的数据库或(b)更新现有的数据库。对于某些与路径相关的更改(例如需要更新数据的更改),需要进行一些自定义设置,但我们有运行前的更新前和更新后的脚本。

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

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

总结:

  • 如果强制执行,所有的数据库更新使用DB鬼更新可执行文件部署的策略,可以“力”开发商一直签入他们的更改,而不管他们是否是在此期间手动部署。
  • 向构建过程添加一个或多个步骤以创建数据库Ghost更新可执行文件将有效地执行测试以验证可以从脚本创建数据库(即,因为DB Ghost创建“源”数据库,即使在创建更新可执行文件包时也是如此),并且如果您添加一个或多个步骤来执行更新包[在您提及的四个测试数据库中的任何一个上],则可以使测试数据库与源代码保持一致。

有一些注意事项和一些局限在什么样的变化“轻松”部署使用此工具(真正的一套相关的工具),但他们都相当轻微(至少对于我的公司):

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

红门提供了如何实现构建自动化纸:http://downloads.red-gate.com/HelpPDF/ContinuousIntegrationForDatabasesUsingRedGateSQLTools.pdf

这是围绕SQL Source Control修建,这与SSMS和您现有的源代码控制系统相集成。

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

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

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

现在让我们从数据库的v2.1到v2.2升级脚本,并且您想验证唯一的特立独行的人是否已经在他的数据库上运行它,您只需搜索VERSION ='v2 .2',如果得到结果,请不要运行此升级脚本。如果需要,可以内置到控制台实用程序应用程序中