数据库部署策略(SQL Server)

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

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

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

第一个问题是,任何脚本都不能写在任何地方,一般每个人都“尝试”把它们放到一个Subversion文件夹中,但是一些懒惰的人只是直接运行脚本,大部分时间都没有人知道谁做了什么什么数据库。

第二个问题是,我们有4个testing数据库,它们总是不符合要求,真正将它们排成一行的唯一方法是从活动数据库中进行恢复。

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

我正在寻找的技术/想法使开发人员很容易logging他们的数据库脚本,使他们可以作为发布程序的一部分运行。 开发人员希望遵循的过程

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

对于这个问题,我select了一个迁移工具: 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"); } } 

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

这对我们的构build来说是一个非常有价值的补充,并且极大地简化了这个过程。

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

阅读K.Scott Allen关于数据库版本控制的系列文章 。
我们build立了一个基于他所描述的技术以受控的方式应用数据库脚本的工具,它运行良好。
这可以作为持续集成过程的一部分,每个testing数据库都有部署到它的变更,当你提交数据库升级脚本的URL。我build议有一个基准脚本和升级脚本,以便您始终可以运行一系列脚本来从当前版本的数据库获取所需的新状态。
尽pipe如此,这仍然需要开发者的一些过程和纪律(所有的改变都需要被编译成新的基本安装脚本和补丁脚本)。

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

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

专业版有一个命令行界面,你可能会用它来设置你的部署程序。

我们使用K. Scott Allen所描述的数据库版本的修改版本。 我们使用数据库发布向导来创build原始基线脚本。 然后,基于SQL SMO的自定义C#工具来转储存储过程,视图和用户function。 包含模式和数据更改的更改脚本由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 

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

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

到这里:

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

向下滚动一下到odetocode.com网站的5个链接列表。 神奇的五部分系列。 我会以此为出发点,想出一个适合您的团队的stream程。

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

编辑:使用红门技术,你只关心创build脚本,而不是升级脚本,因为红门提出了升级脚本。 它也可以让你删除和创build索引,存储过程,函数等。

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

我们使用Visual Studio for Database Professionals和TFS来版本化和pipe理我们的数据库部署。 这使得我们可以像代码一样对待我们的数据库(如签出,签入,locking,查看版本历史,分支,构build,部署,testing等),甚至可以将它们包含在相同的解决scheme文件中。

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

后来,如果在发行版中发现了一个错误,我们可以去发布分支,同时修复代码和数据库。

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

Gus无意中提到了DB Ghost (上图) – 我把它作为一个潜在的解决scheme。

简要介绍我的公司如何使用DB Ghost:

  • 在初始开发阶段合理安排新数据库的模式之后,我们使用DB Ghost的“数据和模式脚本程序”为所有数据库对象(以及任何静态数据)创build脚本(.sql)文件,并签入这些脚本文件转换为源代码控制(该工具将对象分隔成“存储过程”,“表格”等文件夹)。 此时,我们可以使用DB GHost'Packager'或'Packager Plus'工具创build一个独立的可执行文件,以从这些脚本创build一个新的数据库。
  • 对数据库模式的所有更改都通过检入到特定的脚本文件来检入。
  • 在任何时候,我们都可以使用打包程序创build可执行文件,以便(a)创build新的数据库或(b)更新现有的数据库。 对于某些与path相关的更改(例如需要更新数据的更改),需要进行一些自定义,但是我们有运行前的更新前和更新后的脚本。

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

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

总结:

  • 如果您强制执行一项策略,即使用DB Ghost更新可执行文件部署所有数据库更新,则可以“强制”开发人员持续检入其更改,而不pipe这些更改是否在过渡期内手动部署。
  • 在构build过程中添加一个步骤(或多个步骤)以创buildDB Ghost更新可执行文件将有效地执行testing,以validation是否可以从脚本创build数据库(即,因为DB Ghost创build“源”数据库,即使在创build更新可执行文件包),并且如果添加一个或多个步骤来执行更新包[您提到的四个testing数据库中的任何一个],则可以使testing数据库与源代码保持一致。

这个工具(真的是一套相关的工具)“容易”部署的变化有一些限制和局限性,但是它们都很小(至less对于我的公司):

  • 重命名对象必须在其中一个自定义脚本中完成
  • 整个DB总是被更新(例如,单个模式中的对象不能单独更新)使得难以支持主应用程序DB中的客户特定对象

“ 重构数据库 ”一书在概念层面解决了许多这些问题。

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

就真正拉开持续集成式数据库开发而言,由于需要的数据库副本数量很大,所以真正实现了资源的全面快速扩展。 当数据库适合开发人员工作站时,这是非常可行的,但当数据库非常庞大以至于需要跨网格部署时,这是不切实际的。 要做到这一点,你需要每个开发人员1个数据库的副本[使DDL变化的开发人员,而不仅仅是更改过程] + 6个常见副本。 常见副本如下:

  1. INT DEV – >开发人员“检查”他们的重构到INT DEV集成testing。 当集成testing通过时,这个数据库被复制到DEV。
  2. DEV – >这是数据库的“官方”开发副本。 INT DEV定期刷新DEV的副本。 处理新重构的开发人员从DEV获取数据库的全新副本。
  3. INT QA – >除了QA团队外,还有与INT DEV相同的想法。 当集成testing通过这里,这个数据库被复制到QA和DEV *。
  4. QA
  5. INT PROD – >除生产外,与INT QA相同。 当集成testing通过这里,这个数据库被复制到PROD,QA *和DEV *
  6. PROD

*在DEV / QA / PROD行之间复制数据库时,还需要运行脚本来更新与特定环境相关的testing数据(例如,设置质量检查小组中用于testing但不存在于生产中的用户)。

一个可能的解决scheme是考虑在您的testing数据库上实现DML审计,然后将这些审计日志转换为脚本进行最终testing和实时部署。 SQL Server 2008极大地改进了DML审计,但是即使SQL Server 2005也通过触发器支持它。

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

让一个人(数据库pipe理员)致力于pipe理对数据库,尤其是生产数据库的更改,这是一个非常常见的解决scheme。 至于保持X开发和testing数据库的一致性:如果它/他们被许多用户使用,再一次,你最好通过让个人充当变化的“交换所” 如果每个人都有自己的数据库实例,那么他们有责任保持它的顺序,并且当他们需要刷新的基线数据库时,具有中央一致性数据库“源”将是至关重要的。

这里有一个最近的堆栈溢出文章,可能是有趣的: 如何刷新一个testing实例的SQL服务器与生产数据没有使用

红门有一篇文章描述了如何实现构build自动化: http : //downloads.red-gate.com/HelpPDF/ContinuousIntegrationForDatabasesUsingRedGateSQLTools.pdf

这是围绕SQL源代码控制build立的 ,它与SSMS和现有的源代码pipe理系统集成在一起。

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

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

添加一个名为“DB_VERSION”或类似的表。 在每个升级脚本中,向该表中添加一行,可以包含尽可能less的或多个列,但至less我会build议{VERSION,EXECUTION_DATE,DESCRIPTION,EXECUTION_USER}。 现在你已经有了一个具体的logging。 如果有人运行他们自己的未经授权的脚本,你仍然需要按照上面的答案的build议,但这只是一个简单的方法来显着改善你现有的版本控制(即没有)。

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