10

我已经阅读了很多关于数据库版本控制重要性的帖子。但是,我找不到一个简单的解决方案来检查数据库是否处于应有的状态。

例如,我有一个数据库,其中有一个名为“版本”的表(版本号存储在那里)。但是开发人员可以在不更改版本号的情况下访问和编辑数据库。例如,如果开发人员更新存储过程并且不更新版本数据库状态与版本值不同步。

如何跟踪这些变化?我不需要跟踪更改的内容,只需要检查数据库表、视图、过程等是否与保存在版本表中的数据库版本同步。

为什么我需要这个?在进行部署时,我需要检查数据库是否“正确”。此外,并非所有表或其他数据库对象都应被跟踪。是否可以不使用触发器进行检查?是否可以在没有 3rd 方工具的情况下完成?数据库有校验和吗?

假设我们使用 SQL Server 2005。

编辑:

我想我应该提供更多关于我们当前环境的信息——我们有一个“基线”,其中包含创建基本版本所需的所有脚本(包括我们的应用程序的数据对象和“元数据”)。然而,这个“基本”版本的许多安装带有一些额外的数据库对象(额外的表、视图、过程等)。当我们在“基础”版本中进行一些更改时,我们还必须更新一些安装(不是全部) - 那时我们必须检查“基础”是否处于正确状态。

谢谢

4

11 回答 11

6

您似乎违反了“数据库工作的三个规则”的第一条和第二条规则。每个开发人员使用一个数据库并为您的架构使用一个权威来源已经很有帮助。然后,我不确定您的数据库是否有基线,更重要的是,您是否正在使用更改脚本最后,您可能会在Views、Stored Procedures 等以及Branching and Merging中找到其他答案。

实际上,Jeff Atwood 的这篇精彩文章中提到了所有这些链接:让您的数据库处于版本控制之下。必须阅读恕我直言。

于 2009-10-07T23:27:22.447 回答
5

我们使用DBGhost对数据库进行版本控制。创建当前数据库的脚本(连同源代码)存储在 TFS 中,然后使用 DBGhost 生成增量脚本以将环境升级到当前版本。DBGhost 还可以为任何静态/参考/代码数据创建增量脚本。

它需要从传统方法转变思想,但这是一个很棒的解决方案,我推荐的再多也不为过。虽然它是第 3 方产品,但它可以无缝融入我们的自动化构建和部署过程。

于 2009-10-07T22:29:57.180 回答
1

我正在使用基于此 codeproject 文章的简单 VBScript 文件为所有数据库对象生成删除/创建脚本。然后我将这些脚本置于版本控制之下。

因此,要检查数据库是否是最新的或是否有尚未纳入版本控制的更改,我这样做:

  • 从版本控制中获取最新版本的 drop/create 脚本(在我们的例子中是 subversion)
  • 为要检查的数据库执行 SqlExtract 脚本,覆盖版本控制中的脚本
  • 现在我可以用我的 subversion 客户端 (TortoiseSVN) 检查哪些文件与版本控制下的版本不匹配
  • 现在要么更新数据库,要么将修改后的脚本置于版本控制之下
于 2009-10-07T22:28:58.587 回答
1

您必须限制对所有数据库的访问,并且只允许开发人员访问本地数据库(他们开发的地方)和他们可以进行集成的开发服务器。最好的办法是让他们只能在本地访问他们的开发区域并通过自动构建执行集成任务。您可以使用 redgates sql compare 等工具对数据库进行比较。我建议您将所有更改保存在源代码控制(.sql 文件)下,这样您就可以了解谁在何时做了什么,并且可以在需要时恢复数据库更改。

我还希望能够让开发人员运行本地构建脚本来重新启动他们的本地开发箱。这样他们就可以随时回滚。更重要的是,他们可以创建集成测试来测试他们的应用程序(存储库和数据访问)的管道以及以自动化方式隐藏在存储过程中的逻辑。运行初始化(重置数据库),运行集成测试(在数据库中创建绒毛),重新初始化以将数据库恢复到干净状态等。

如果你是一个 SVN/nant 风格的用户(或类似用户),在你的存储库中有一个分支概念,那么你可以在 DotNetSlackers 上阅读我关于这个主题的文章:http: //dotnetslackers.com/articles/aspnet/Building-a- StackOverflow-inspired-Knowledge-Exchange-Build-automation-with-NAnt.aspxhttp://dotnetslackers.com/articles/aspnet/Building-a-StackOverflow-inspired-Knowledge-Exchange-Continuous-integration-with-CruiseControl- NET.aspx

如果你是一个 perforce 多分支的构建大师,那么你将不得不等到我写一些关于这种自动化和配置管理的东西。

更新

@Sazug:“是的,当我们使用基本脚本 + 附加脚本时,我们会使用某种多分支构建 :) 没有完整文章的那种自动化的任何基本技巧?” 最常见的数据库有两种形式:

  • 您在新的非生产类型环境中控制数据库(仅限活动开发人员)
  • 一个生产环境,您可以在其中积累实时数据

第一次设置要容易得多,并且可以从 dev 到 prod 完全自动化,并在需要时包括回滚 prod。为此,您只需要一个脚本文件夹,其中对数据库的每次修改都可以保存在 .sql 文件中。我不建议您保留 tablename.sql 文件,然后像使用 .cs 文件一样对其进行版本化,其中随着时间的推移,对该 sql 工件的更新实际上会在同一个文件中进行修改。鉴于 sql 对象彼此之间非常依赖。当您从头开始构建数据库时,您的脚本可能会遇到重大更改。出于这个原因,我建议您为每次修改保留一个单独的新文件,并在文件名的前面加上一个序列号。例如像 000024-ModifiedAccountsTable.sql 这样的东西。然后,您可以使用自定义任务或 NAntContrib 之外的其他内容,或直接执行众多 ??SQL.exe 命令行工具之一,针对从 000001-fileName.sql 到最后一个文件的空数据库运行所有脚本在 updateScripts 文件夹中。然后将所有这些脚本签入到您的版本控制中。而且由于你总是从一个干净的数据库开始,如果有人的新 sql 破坏了构建,你总是可以回滚。

在第二种环境中,自动化并不总是最佳途径,因为您可能会影响生产。如果您正在针对/针对生产环境积极开发,那么您确实需要一个多分支/环境,以便您可以在实际推动生产环境之前测试您的自动化方式。您可以使用与上述相同的概念。但是,您不能真正在 prod 数据库上从头开始,并且回滚更加困难。出于这个原因,我建议在您的构建过程中使用类似的 RedGate SQL Compare。.sql 脚本已签入以进行更新,但您需要在运行更新之前自动执行 staging db 和 prod db 之间的差异。然后,您可以尝试同步更改并在出现问题时回滚 prod。还,在自动推送 sql 更改之前,应采取某种形式的备份。在生产中做任何没有人眼观察的事情时要小心!如果您在所有开发/质量/暂存/性能环境中进行真正的持续集成,然后在推送到生产环境时执行一些手动步骤……那真的还不错!

于 2009-10-07T22:38:16.760 回答
0

第一点:没有“规矩”,就很难保持秩序。或者以您的示例为例-开发人员在没有通知的情况下更改任何内容都会给您带来严重的问题。

无论如何-您说“不使用触发器”。这有什么具体原因吗?

如果没有,请查看 DDL 触发器。这样的触发器是检查某事是否发生的最简单方法。

你甚至可以记录发生了什么。

于 2009-10-07T22:30:00.090 回答
0

希望有人有比这更好的解决方案,但我使用几种方法来做到这一点:

  • 有一个“主干”数据库,这是当前的开发版本。所有工作都在这里完成,因为它正准备包含在一个版本中。
  • 每次发布完成时:
    • 上一个版本的“干净”数据库被复制到新版本,例如,“DB_1.0.4_clean”
    • SQL-Compare用于将更改从主干复制到 1.0.4_clean - 这也允许准确检查包含的内容。
    • 再次使用 SQL 比较来查找以前版本和新版本之间的差异(从 DB_1.0.4_clean 更改为 DB_1.0.3_clean),这会创建一个更改脚本“1.0.3 到 1.0.4.sql”。

我们仍在构建工具来自动化这部分,但目标是有一个表来跟踪数据库的每个版本,以及是否应用了更改脚本。升级工具会查找最新条目,然后逐个应用每个升级脚本,最终数据库处于最新版本。

我没有这个问题,但是保护 _clean 数据库不被其他团队成员修改是微不足道的。此外,由于我事后使用 SQL 比较来生成更改脚本,因此开发人员无需随时跟踪它们。

  • 我们实际上做了一段时间,这是一个巨大的痛苦。这很容易忘记,同时,所做的更改不一定成功 - 因此使用单独创建的更改脚本创建的完整升级脚本有时会添加一个字段,然后将其删除,全部在一个版本。如果有索引更改等,这显然会很痛苦。

SQL compare 的好处是它生成的脚本在事务中——如果失败,它会将整个事情回滚。因此,如果生产数据库以某种方式进行了修改,则升级将失败,然后部署团队实际上可以在生产数据库上对 _clean 数据库使用 SQL 比较,并手动修复更改。我们只需要这样做一两次(该死的客户)。

.SQL 更改脚本(由 SQL Compare 生成)存储在我们的版本控制系统(subversion)中。

于 2009-10-07T22:34:08.557 回答
0

如果您有 Visual Studio(特别是数据库版本),则Database Project可以创建一个并将其指向 SQL Server 数据库。该项目将加载模式并基本上为您提供许多其他功能。它的行为就像一个代码项目。它还为您提供了为整个表格和内容编写脚本的优势,因此您可以将其保存在 Subversion 下。构建项目时,它会验证数据库是否具有完整性。这很聪明。

于 2009-10-07T23:08:31.430 回答
0

在我们的一个项目中,我们将数据库版本存储在数据库中。

对数据库结构的每次更改都被编写到单独的 sql 文件中,除了所有其他更改之外,该文件还会增加数据库版本。这是由更改数据库结构的开发人员完成的。

部署脚本检查当前数据库版本和最新更改脚本,并在必要时应用这些 sql 脚本。

于 2009-10-07T23:22:48.027 回答
0

我必须同意这篇文章的其余部分。数据库访问限制将解决生产问题。然后使用 DBGhost 或DVC之类的版本控制工具将帮助您和团队的其他成员维护数据库版本控制

于 2010-06-03T23:47:50.837 回答
0

我同意其他帖子,即开发人员不应有权更改生产数据库。开发人员要么应该共享一个通用的开发数据库(并冒着互相踩踏的风险),要么他们应该拥有自己的个人数据库。在前一种情况下,您可以使用 SQL Compare 之类的工具部署到生产环境。在后一种情况下,您需要在开发生命周期期间定期同步开发人员数据库,然后再升级到生产环境。

在 Red Gate,我们很快将发布一个新工具,SQL 源代码控制,旨在简化此过程。我们将集成到 SSMS 中,只需单击一个按钮即可在源代码控制中添加和检索对象。如果您有兴趣了解更多信息或注册我们的抢先体验计划,请访问此页面:

http://www.red-gate.com/Products/SQL_Source_Control/index.htm

于 2009-10-28T23:11:31.893 回答
0

首先,您的生产数据库不应该被开发人员访问,或者开发人员(和其他所有人)应该受到严格的指示,即不得在变更控制系统之外对生产系统进行任何类型的更改。

变更控制在您期望工作的任何系统中都至关重要(在整个系统中涉及超过 1 名工程师)。

每个开发者都应该有自己的测试系统;如果他们想对此进行更改,他们可以,但是系统测试应该在一个更可控的系统测试系统上进行,该系统具有与生产相同的更改 - 如果你不这样做,你就不能依赖发布工作,因为它们正在不兼容的环境中进行测试。

进行更改时,应创建并测试适当的脚本,以确保它们完全适用于当前版本,并且回滚有效*

*您正在编写回滚脚本,对吗?

于 2009-10-08T06:32:58.680 回答