SQL Server数据库更改工作流程最佳实践

8

背景

我们的组有4个SQL Server数据库:

  • 生产环境
  • 用户验收测试环境(UAT)
  • 测试环境
  • 开发环境

我在开发环境工作。当需要推广我所做的对象(表、视图、函数、存储过程)时,我会向我的经理提出请求,她会将它们推广到测试环境。经过测试后,她会向管理员提交请求,将它们推广到用户验收测试环境(UAT)。在成功的用户测试后,同一管理员会将它们推广到生产环境。

问题

整个过程有几个不方便之处:

  1. 每个人都必须手动跟踪他们的更改。如果我更新、添加或删除任何对象,我需要跟踪它们,以便我的推广请求包含我所做的所有事情。理论上,如果我漏掉了什么,测试或用户验收测试应该能够发现,但这并不确定,而且这也浪费了测试人员的时间。
  2. 我进行的许多更改都是迭代的,并且在GUI中完成的,这意味着没有记录我所做的更改,只有最终结果(至少就我所知)。
  3. 我们正在构建数据集市的早期阶段,因此大部分更改(按数量计算)都是微小的事情:更改列的数据类型,随着我们明确表用途而修改表名,调整函数和存储过程等。

问题

人们已经做这种工作数十年了,所以我想象中肯定有更好的方法来管理这个过程。我希望能够运行两个数据库之间的差异比较,查看结构的不同之处,使用该差异生成更改脚本,并将其用作我的推广请求。这可行吗?如果不行,是否有其他组织此过程的方式?

值得一提的是,我们是100%的Microsoft店,刚刚更新到SQL Server 2008,因此该套件中提供的任何工具都可以使用。


我应该澄清一下,我不一定在寻找差异工具。如果这是同步环境的最佳方法,那么没问题,但如果有更好的方法,我会寻找它。

Ruby on Rails中的迁移就非常好地实现了我想要的功能。语法简单易懂,所有更改都自动且默认情况下都有很好的文档记录,确定需要运行哪些迁移几乎是轻而易举的。我希望SQL Server中也有类似的东西。

我的理想解决方案是:1)易于使用;2)难以出错。Rails迁移两者都具备,但在SQL Server上所做的一切都不具备这些特点。

9个回答

4
在我们的团队中,我们处理数据库更改的方式如下:
  • 我们生成一个创建完整数据库的脚本并将其与其他更改一起检入版本控制。我们有4个文件:表、用户定义的函数和视图、存储过程和权限。这是完全自动化的-只需双击即可生成脚本。
  • 如果开发人员需要更改数据库,则在其本地数据库上进行更改。
  • 对于每个更改,我们创建更新脚本。这些很容易创建:开发人员重新生成他的本地数据库的db脚本。由于版本控制,现在所有更改都很容易识别。大多数更改(新表、新视图等)可以简单地复制到更新脚本中,其他更改(例如添加列)需要手动创建。
  • 要么在我们的公共开发数据库上测试更新脚本,要么通过将本地数据库回滚到上次备份来测试更新脚本-在开始更改数据库之前创建的备份。如果它通过了,那么就是提交更改的时候了。
  • 更新脚本遵循命名约定,因此每个人都知道按照什么顺序执行它们。

这对我们来说运作得相当不错,但仍需要一些协调,如果有几个开发人员大量修改相同的表和视图。虽然这种情况并不经常发生。

重要的点是:

  • 只有本地开发人员的数据库除外,数据库结构只能通过脚本进行修改。这很重要。
  • SQL脚本由源代码控制进行版本控制-可以在过去的任何时间创建数据库
  • 定期创建数据库备份-至少在对数据库进行更改之前
  • 对于数据库的更改可以很快完成-因为这些更改的脚本相对容易创建。

然而,如果您的项目有许多持续时间较长的开发分支,则可能无法很好地运作。

这绝不是完美的解决方案,需要采取一些特殊预防措施。例如,如果有可能根据数据库中存在的数据而失败的更新,则应在生产数据库的副本上测试更新。

与Rails迁移不同,我们不创建撤消更新更改的脚本。但是,无论如何,至少在数据方面(删除列的内容即使重新创建该列也会丢失)都不总是可能的。


2
从VS 2012开始,可以查看数据库项目,这些项目可以在Visual Studio内集成和促进更新脚本的创建和更新。上面的答案仍然适用。这里可以找到一些有用的文章:http://arcanecode.com/tag/visual-studio-database-projects/ - marapet

3

版本控制和数据库

所有问题的根源都在于在UI中进行更改。SSMS是DBA工具,而不是开发人员工具。开发人员必须使用脚本来对数据库模型/架构进行任何更改。对元数据进行版本控制,并从每个版本N升级到版本N + 1的升级脚本是被证明可靠的唯一方法。这是SQL Server自身部署以跟踪元数据更改(资源数据库更改)的解决方案。

像SQL Compare或vsdbcmd之类的比较工具以及来自VS数据库项目的.dbschema文件只是失败了适当版本化方法的商店的最后手段。它们可以在简单情况下工作,但我看到它们在严重部署中都会失败得惨烈。如果工具试图复制数据,则人们绝不能信任一个工具对+5TB表进行更改...


1
使用脚本更新数据库并手动跟踪更新脚本,正是我试图避免的情况。 - kubi
1
你不需要“追踪”更新。你把数据库更新视为代码的改进和特性。你把脚本视为源代码树的一部分,像源代码一样将它们纳入版本控制,并像源代码一样进行审核等处理。这与你不回避编写项目.cs文件的方式相同。 - Remus Rusanu

2

RedGate销售SQL Compare, 这是一款出色的用于生成更改脚本的工具。

Visual Studio也有支持数据库比较的版本,这以前被称为Database Edition

在我工作的地方,我们早就放弃了Dev/Test/UAT/Prod之间的分离,转而采用非常快速的发布周期。如果我们在生产中出现问题,我们会尽快修复它。虽然这样做让我们的客户更加满意,但在风险规避的企业中,这可能很难推广。


2

有几种工具可供您使用。其中之一是来自Red-Gate的SQL Compare。非常棒且值得推荐。SQL Compare可以让您对比两个数据库之间的模式差异,并为您构建SQL更改脚本。

请注意,他们已经在开发一个SQL Server源代码控制产品了。

另一个(如果您使用Visual Studio)是Visual Studio的模式和数据比较功能(不确定哪些版本)。


SQL源代码控制将在六月底之前处于Beta阶段,届时我们希望能够发布最终版本。该构建目前可从我们的网站上下载(我是Red Gate的产品经理)。 - David Atkinson
SQL Source Control 1.0现已发布,可在http://www.red-gate.com/products/SQL_Source_Control/index.htm上获取。 - David Atkinson

2

同意 SQL Compare 是一个很棒的工具。

然而,我们不会对数据库结构或对象进行任何更改,除非它们已经被脚本化并保存在源代码控制中,就像所有其他代码一样。这样你就能够准确地知道哪些版本属于你正在推广的版本,因为你拥有该特定版本的脚本。

通过 GUI 进行结构性更改是一个不好的想法。如果你有大量的数据,在 SQL Server 中使用 alter table 至少比使用 GUI 要慢得多。你只需要使用经过测试的脚本来对生产环境进行更改。


1

我同意由marapet提出的每个更改必须脚本化的评论。

然而,你可能遇到的问题是创建、测试和跟踪这些脚本。

看看DBSourceTools中使用的修补引擎。

http://dbsourcetools.codeplex.com

它专门设计用于帮助开发人员将SQL服务器数据库纳入源代码控制。

此工具将允许你将数据库基线置于特定点,并创建命名版本(v1)。

接着,创建一个部署目标——并将命名版本递增至v2。

为架构或数据的任何更改添加补丁脚本到补丁目录中。

最后,检查数据库和所有补丁以将其与开发者一起分发到源代码控制。

这给你带来了一个可重复的过程,可以测试从v1到v2要应用的所有补丁。

DBSourceTools还具有帮助你创建这些脚本的功能,例如模式比较或脚本数据工具。

完成后,只需将补丁目录中的所有文件发送给你的DBA以升级从v1到v2即可。

玩得开心。


0

0
  1. 在版本控制表中保留数据库版本
  2. 保留成功应用的脚本文件名
  3. 保留已应用每个 SQL 脚本的 MD5 校验和。计算 MD5 校验和时应忽略空格。必须有效。
  4. 保留应用脚本的人员信息,以及脚本应用时间的信息
  5. 应用程序启动时应验证数据库
  6. 新的 SQL 脚本应自动应用
  7. 如果已应用的脚本的 MD5 校验和发生变化,则应抛出错误(在生产模式下)
  8. 已发布的脚本不能更改。在生产环境中,它必须是不可变的。
  9. 脚本应编写成可以应用于不同类型的数据库的方式(参见 Liquibase)
  10. 由于大多数 DDL 语句在大多数数据库上都是自动提交的,因此最好每个 SQL 脚本只有一个 DDL 语句。
  11. DDL SQL 语句应以一种可以多次执行而不出错的方式运行。这对于开发模式非常有帮助,当您可能需要多次编辑脚本时。例如,仅在不存在表时创建新表,甚至在创建新表之前删除表。这将有助于您在未发布的脚本中进行开发,更改它,清除此脚本的 MD5 校验和,再次运行它。
  12. 每个 SQL 脚本应在其自己的事务中运行。
  13. 每次数据库更新后都应删除并重新创建触发器/存储过程。
  14. SQL 脚本保存在版本控制系统(如 SVN)中
  15. 脚本名称包含提交日期、现有(JIRA)问题 ID 和简短描述
  16. 避免在脚本中添加回滚功能(Liquibase 允许这样做)。这会使它们编写和支持起来更加复杂。如果每个脚本恰好只有一个 DDL 语句,并且 DML 语句在事务内运行,即使脚本失败,解决它也不会是一个大问题。

0

这是我们一直成功使用的工作流程:

  • 开发实例:使用MSSQL Studio在数据库中创建/更新/删除SQL对象,并将所有操作保存到我们代码每个版本中包含的脚本中。
  • 移动到生产环境:我们使用Microsoft Visual Studio中的SQL Schema Compare比较开发和生产数据库的模式。我们使用相同的工具更新生产环境。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接