多应用实例的数据库设计理论

时间:2009-10-25 18:21:49

标签: sql-server

我正在开发一个SaaS项目,每个客户都有一个应用程序实例(customer1.application.com,customer2.application.com等),理想情况下,每个客户都有自己的“自己”空间。 DB。当前计划是为每个客户创建一个数据库,并将该应用程序的实例部署到Web场中。我们的想法是,每个客户都可以选择退出升级以维持现状(这是我们投资者真正想要的,主要是因为他讨厌Facebook如何不断改变其运作方式。)

昨晚我试图向我的两个测试帐户推出更改数据库的更新。虽然随之而来的错误是我的错(忘记了DDL中的一个小但显然非常重要的变化),我开始担心我的整体操作理论,因为缺少一个ALTER COLUMN语句和整个升级周期可能会被吹地狱。所以经过这么长时间的建立,这是我的问题:

1)有没有办法在两个数据库(“测试”生产数据库和实际生产数据库)之间进行差异,以准确记录每个正在进行的更改?

2)我应该考虑另一个数据库(和/或应用程序)设计模型吗?我知道如果我拿走支持多个版本的应用程序,我实际上删除了很多长期支持头痛。

5 个答案:

答案 0 :(得分:2)

  1. 您永远不应该手动更换数据库。通过执行所有DDL更改的脚本等来完成...

    理想情况下,应该有一个通用的DB发布脚本,它使用DDL版本作为配置/输入。

    (并且DDL更改应使用版本控制系统中的特定标记进行标记)

  2. 你可以去微软路由:支持多个版本令人头疼 - 只需将X之前的所有版本(比如两个版本)指定为不支持。这样,您可以支持最后2-3个版本,但不会浪费任何资源,同时在很大程度上允许每个客户端的灵活性。

  3. 你应该像你提议的那样仔细权衡版本化app / DB系统的优点/缺点。

    列出专业人士(例如安抚投资者,当您提到的版本意外更改时客户的积极体验 - 转化为保留/添加需要此类功能的新客户的边际概率,以及一个简单的方法来进行BETA / UAT测试,加上一种错误的方法,通过将客户端的数据从先前版本加载到DB模式中来回滚模式更改。)

    列出缺点(数据库空间成本,实施时间成本,支持成本)

  4. 比较两者并确定哪个更适合您的业务。

答案 1 :(得分:2)

Redgate的SQL Compare在比较和区分两个SQL Server数据库方面做得很好(警告:商业第三方产品)。此外,我认为那里有免费的东西可以做同样的事情。

如果您希望能够在产品的旧版本上留下一些客户,那么维护每个客户一个数据库的模型可能更有意义,其中包含用于在源代码下构建每个数据库版本的脚本控制。这使您的客户彼此隔离,甚至允许您在某些客户上切换数据库供应商(例如从SQL Server到Oracle)或版本(即从SQL Server 2000到Sql Server 2005),同时保持其他客户使用旧版本。

答案 2 :(得分:2)

手动运行脚本无效。对于此事,也不是差异工具。 Diff适用于2,4个10个数据库。但是没有扩展,因为你需要的是存在故障时的可靠性(脱机数据库,服务器重启所有这些)。

通过安排升级脚本进行部署。例如,看看MySpace如何为超过1000个数据库执行此操作:MySpace Uses SQL Server Service Broker to Protect Integrity of 1 Petabyte of Data。关键是他们使用有保证的,可靠的交付机制(SSB)来部署架构维护脚本。您需要一个异步,可靠的机制来运行脚本,因为目标数据库可能处于脱机状态,运行计划维护,未完成等,并且Service Broker等可靠的交付机制可以处理所有重试和相关问题(处理重复,确认等)。您还可以查看Asynchronous procedure execution以获取如何通过SSB处理脚本执行的示例。

对于脚本本身,我建议您开始将数据库架构和配置数据视为版本化资源。我已经多次解决这个问题,例如。见Do you put your database static data into source-control ? How?

<强>更新

我想我有一些解释为什么我会考虑采用错误的方法。为了说清楚,我说的是数百个服务器和数千个数据库的部署。最初的帖子将自己与facebook进行比较,我希望他们能够成功达到这个规模,但问题也是关于设计原则,所以我说讨论云级别的规模是合适的。

我发现diff工具存在两个问题:

  • 状况。所有diff工具都通过连接'master'和'copy'来工作,因此只有当两者都在线时它们才能完成工作。这会产生热点,单点故障,“主”副本,其可用性对于部署升级至关重要。高可用性总是需要付出代价。它还将“复制”可用性问题留作次要实现细节,升级方案必须自己处理重试和超时以及与客户端断开连接(无论如何都不是一个小问题)。

  • 原子性。 diff工具期望“master”的稳定模式。这实际上会在升级过程中冻结'master'。虽然这可以在小规模上进行控制,但是在大规模上它会成为一个问题,因为将主机本身升级到v.N + 1会成为对抗所有数千个数据库的竞争,当有些数据库可能仍然从v.N-1升级时

将升级脚本发送到“副本”的基于脚本的解决方案可以解决这两个问题。另外,基于VSDB .dbschema vsdbcmd.exe的差异工具比“实时”差异工具更好,因为“主”dbschema文件可以传送到“复制”机器并将整个升级过程转换为本地操作。

总的来说,我也相信使用元数据版本控制的基于脚本的升级是基于差异的升级,因为我已经在Q1525591的链接中讨论了测试和源代码控制的原因。

答案 3 :(得分:2)

深思熟虑:

代码升级比DB Schema升级更频繁。确保您有一个非常好的 SCM来处理代码升级。我们使用git取得了巨大成功。

代码易于管理,数据库不易(相比之下)。原因是它们是可变的,并改变每一刻。此外,它们很难回滚(可能,但耗时,停机时间)。因此,我们必须以一种简单的方式来跟踪架构更新(以及相关的数据更改),并能够将其应用于其他类似的数据库。


应为每个数据库模式版本提供唯一的顺序整数版本号。从每说100开始。

每次必须升级时,请编写一个像

这样的sql脚本
  • 100-101.sql
  • 101-102.sql
  • 102-103.sql

每个脚本的工作是为该特定版本执行升级。它可以像添加表一样简单,也可以像重新安排外键一样复杂。但无论如何,他们的设计目标都是可靠

您可以在测试期间多次应用任何给定的脚本(对新数据),以确保它能按预期工作。


因此,当您发现自己需要将客户端从版本130升级到180时,您可以安全地应用sql脚本(IN ORDER),并且您将到达正确的目的地。

答案 4 :(得分:0)

  

如果我带走支持倍数   我的应用程序的版本   实际上删除了很多长期   支持头痛

任何变化,无论多么小,都有可能打破对某人重要的事情。

因此,如果您有多个客户,那么为客户1推出一个修复程序会让客户2感到不安。它甚至不一定是一个错误的版本;它可能只是他们不同意的行为的变化。对于大多数客户而言,不控制发布计划是不可接受的。

所以我建议你为每个客户保留不同的代码库。只有在与客户达成协议后才能推出修复程序。

有许多客户将这种方法破坏了(想想雅虎邮件),但是阅读你的问题我认为你安全地低于这个数字。对于比较工具,我不禁同意暗示Redgate的SQL Compare的帖子。