2

我们公司有一个在 Asp.net 和 Sql Server 2008 中开发的与人力资源管理相关的产品,并安装在 20-30 个客户端中。由于每个客户的要求,该软件都在不断开发中。

现在,当进行一些新的更改并且某些使用旧版本的客户端要求进行一些更改时,我们必须安装具有最新数据库结构的最新版本代码。现在我们必须使用查询升级他们的数据库并且我们必须跟踪每个客户端数据库结构以生成升级查询。

目前,我们正在存储每个客户端数据库,并使用 Red Gate SQL Compare 等工具生成 sql 进行升级。随着客户端的增加,这个过程非常繁琐,那么这个过程的替代方法是什么,我们可以使用数据库版本控制或任何其他替代方法,使用安装程序(如 installaware)使用最新的数据库引用自动更新客户端数据库?

4

3 回答 3

1

Red Gate 正在考虑使部署更容易。

我是 Red Gate 的产品经理,最近我写了一份名为“使用 Red Gate 工具的自动化部署”的白皮书,其中介绍了一种可能的解决方案。 http://assets.red-gate.com/delivery/deployment-manager/assets/pdf/automated-deployment-whitepaper.pdf

该方法本质上是将 Web 应用程序和数据库组件都转换为可以由管理系统部署的包。数据库是最难的部分,论文提出了两种方法:

  • 动态升级。升级脚本在部署时创建。这对于可以轻松重建数据库的开发和测试环境很有用。数据库包包含数据库的结构,通常作为脚本文件夹。

  • 静态升级。为您知道当前部署的每个版本创建包时,通常在 CI 构建结束时创建升级脚本。(管理系统跟踪部署了哪些版本。)在部署时,使用正确的升级脚本。还有部署前和部署后验证步骤,以确保数据库未更改,升级脚本将正常运行并且升级脚本确实运行成功。这种方法非常好,因为它允许测试升级脚本本身,因为它是通过开发、测试、暂存、生产等进行部署的。它还允许 DBA 在流程的早期审查脚本。

于 2012-09-11T11:28:06.800 回答
0

我怀疑你会为你的问题找到一个最佳答案,因为可以有很多方法来实现你的目标,但我可以分享我们的过程以及我在过去 10 年中所做的事情所获得的一些见解描述。也许他们会帮助您确定适合您的解决方案。

首先,更新客户端数据库是一个难题。自从您安装了您的软件后,您永远不会真正知道他们可以对数据库做什么。我让客户将他们自己的表、视图甚至索引添加到我们的系统表中,因为他们认为系统需要它们。在升级目标数据库时,所有这些都会让人头疼,因为您不一定知道一开始的数据库状态。

其次,我喜欢你最初认为升级数据库的安装程序将是要走的路。然后我开始更多地考虑这个问题,在我们的案例中,至少 DBA 通常不是升级前端软件的人。我们还从许多客户那里听说,在服务器上安装任何东西对他们来说都是不可能的,所以回到第一条。

最后,我们选择构建自己的可执行文件,其中包含升级脚本以及 DBA \ 最终用户连接到服务器 \ 数据库并运行升级过程的能力。

(在我们的例子中,我们使用了许多包含我们专有商业智能的加密存储过程,这就是为什么我们不只是将脚本提供给客户。)

如果您还没有这样做,请将您的数据库纳入源代码控制!Visual Studio 和 Red-Gate 各自提供产品来促进这一点。我都用过,没有特别的偏好,但我会说使用你和你的团队感到舒服的东西。

当我们发布更新时,我们执行从源代码控制中的最新版本数据库到早期版本数据库的差异。我们寻找任何新对象和任何更改的对象 - 我们很少删除对象,但这可能也是您需要的。

一旦我们知道数据库中发生了什么变化,我们就会非常有条不紊地通过更改列表创建幂等脚本来执行必要的更改。这是一个非常繁琐的过程,但有助于确保客户获得轻松的升级体验。本质上,我们对这个过程所做的是防御性编程——而不是假设数据库中存在表、视图、存储过程、函数等,我们首先检查以确保该项目存在。如果是这样,我们也许可以完全跳过该 DDL 语句。在其他情况下,我们可能希望删除对象并重新创建它。

需要明确的是,我们从不删除表,但我们经常会删除其他对象并重新创建它们以确保对象是最新的。

脚本以正确的顺序打包到我们的可执行文件(我们内部构建的解决方案)中(例如,如果您要添加一个表和一个引用该表的视图,则需要在视图之前创建该表)。

顺便说一句,Red-Gate 提供了一个现在为您执行此操作的工具,尽管我还没有在生产中亲自使用它。

一旦我们对更新已正确打包感到高兴,我们就会尝试破解它!我们在我们支持的所有 SQL Server 版本(例如 2000、2005、2008、2012)上针对我们数据库的各种版本进行测试——真正的旧版本、我们以一种或另一种方式修改过的数据库。如果我们发现一种情况不起作用,我们会修复我们的脚本,直到它发生。

我还应该提到,我们的数据库模式有一个日志表,我们的更新模块写入该日志表,以便记录执行更新的时间、执行者以及哪些对象是该更新的一部分。这有时有助于排除故障。

虽然我们的实用程序不会在执行脚本之前备份要升级的数据库,但我们可以,而且我建议您将其视为过程的一部分。(我们的文档强调了这一点的重要性,并且我们多年来与之合作的大多数 DBA 也自然而然地这样做了,因此我们认为没有必要将其写入实用程序中)。

数据库更新实用程序与我们的软件更新打包在一起,并作为整个产品的另一个组件分发,并且可以由在我们客户端站点的数据库中拥有适当凭据和权限的任何用户执行。

虽然多年来这个过程对我们来说效果很好,但随着新工具在市场上的引入以及我们遇到客户遇到的错误,我们会继续对其进行改进。开发一个有效的过程可能需要一段时间,所以尽量不要在任何给定时间咀嚼太多。对我们来说,将数据库纳入源代码控制是最大的关键。一旦我们这样做了,事情就开始逐渐到位。

于 2012-09-10T16:43:02.610 回答
0

考虑支持导出/导入功能。

“导出”功能本质上是创建已知/预期表的备份到不同名称的源。“导入”函数创建最新版本对象的空副本,然后从导出到其他源的表中导入行。

正如 Tim Lentine 所说,无论他们应用了什么定制,他们都必须重新应用。您的企业将需要决定他们愿意在多大程度上花费资源在升级期间重新应用客户端自定义。

我会告诉客户他们需要先进行备份(假设他们有 DBA)或支持数据库备份功能(如果他们没有)然后导出然后导入。

当然,这假设您的更改始终是向后兼容的。

这是一个简单、便宜的解决方案,如果你能侥幸逃脱的话。如果没有,正如 Tim Lentine 所说,它会变得非常困难和混乱。

高温高压

于 2012-09-10T17:05:37.713 回答