为每个客户创建数据库会遇到什么问题?

Rik*_*ood 55 mysql database-design database-recommendation

我从 stackoverflow 播客中记得Fog CreekFogbugz为每个客户使用一个数据库。我认为这意味着 Fogbugz On Demand 服务器拥有数以千计的数据库。

我们刚刚开始开发一个网络应用程序,并有一个类似的问题需要解决(许多客户拥有自己的独立数据)。

使用每个客户的数据库会出现什么问题?我该如何解决它们?

我的初步想法

每个客户数据库的优势

  • 更简单的数据库架构
  • 更简单的备份 - 您可以依次备份每个客户,而不会真正影响其他客户。
  • 可以轻松导出给定的客户数据。
  • 更好的缓存性能 - 写入一个更活跃的表只会影响执行写入的单个客户。
  • 更容易跨硬件扩展。例如,当我们需要从 1 台服务器增加到 2 台服务器时,我们只需将一半的客户转移到新服务器上。

缺点

  • MySQL能应付5000个数据库吗?性能会很差吗?
  • 对架构的更改可能难以复制到所有数据库中。我们真的必须为此制定一个自动化计划,例如对模式进行版本控制,以及一个了解如何将数据库从一个版本转换为另一个版本的脚本。
  • 做我们所有客户共同的事情可能会很尴尬或不可能
  • 与上述类似,但我们想要对所有客户执行的任何分析都可能是不可能的。例如,我们应该如何跟踪所有客户的使用情况?

Tho*_*mas 44

这种解决方案称为多租户设计,其中每个租户(客户)都有自己的数据库。鉴于此,对于单一数据库的替代方法还有其他一些考虑:

  1. 使用单个数据库,无论如何每个人都必须使用相同的版本。升级某些客户而不是其他客户是不可能的。如果客户想要一个尚未准备好广泛发布的应用程序的修补程序,这可能会出现问题。
  2. 对于单个数据库,当您进行升级时,每个客户端都会停机。如果出现问题,每个客户都会被搞砸。
  3. 对于单个数据库,限制资源要困难得多。即,如果一个客户端正在敲打数据库,则很难为他们提供与其他人分开的更多资源。
  4. 允许用户托管他们自己的应用程序版本要困难得多。如果您正在构建一个将由大型企业使用的解决方案,这通常是一个非启动项。他们的 IT 部门希望完全控制对系统的访问。
  5. 向外扩展数据库可能比向上扩展更便宜。即,必须投资更快的硬件来托管一个数据库来统治所有数据库可能比将客户扩展到更小、更便宜的数据库服务器的成本更高。我不能肯定地说这个,因为它在很大程度上取决于服务器软件。如果您坚持使用 MySQL,这可能是正确的,因为许可成本可以忽略不计。但是,如果您升级到 SQL Server,除非您使用 VPS 环境以及扩展与扩展的成本收益变化,否则扩展会变得更加昂贵。但是,我可以说,一旦您的数据库变得非常大,管理就需要更高水平的专业知识。非常大的数据库需要处理多个文件组并将某些索引推送到不同的主轴以获得更好的性能。简而言之,他们很快就会变得复杂。

拥有单独的数据库确实意味着您必须构建一个更新机制,使数据库版本与应用程序/站点版本相匹配。但是,单独的数据库确实提供了出色的数据隔离,并且 IMO 的托管成本较低。它不是适用于所有场景的解决方案。如果您的系统永远不会在您的主机之外托管,并且需要快速扩展客户,并且希望所有用户都使用相同版本的应用程序和数据库架构,那么拥有单个数据库当然是更好的方法。

  • 我使用共享数据库和多租户独立数据库设置运行 Web 服务。有时两者都是正确的选择。在我为每个客户拥有单独数据库的应用程序中,我遇到了完全相同的 5 个原因,它是该应用程序的正确选择。 (2认同)
  • 需要注意的一点是:我将所有客户都放在一个数据库中,并使用数据库代码层来确保每个查询都包含客户特定的条件。危险的一点是,当您必须走出数据库层来执行一些非常具体的操作时 - 例如一个可怕的大型复杂查询,其中数据可能会从意外的地方泄漏。 (2认同)

eie*_*fai 15

根据我的经验,您不应该为每个客户创建一个数据库。让我给你举个例子:

去年我使用了 70 个数据库(远少于 5000 个),每个数据库都具有相同的架构。理论上,事情会按计划进行(正如您在优势部分中提到的),但实际上并非如此。我们在更新架构、用户支持、软件更新等方面遇到了很多问题。太可怕了。

我们使用了 Firebird,并且在产品发货后我被聘用了,但这让我知道永远不要使用分离的数据库。

我并不是说你不能完成它,我是说事情可能会出错,老实说,你的优势列表听起来不够吸引人去冒险。它们中的大多数可以通过单个数据库来完成。

  • 如果您能举例说明究竟出了什么问题,那就太好了。当然,让所有数据库保持最新更难,但要决定我们必须能够衡量利弊。 (2认同)

Joe*_*Joe 9

您可能希望保留另一个数据库来跟踪每个客户的版本,这样您就可以跟踪哪些已经或没有经过上一轮修改。

编写升级脚本不会那么困难……您可以编写一些内容来查看数据库目录并应用必要的更改以使每个数据库都更新到最新版本,可能会跳过那些由于某种原因不应升级的数据库。

由于 mysql '数据库' 只是模式,正如 Gaius 指出的那样,如果它们都从同一个服务器实例运行,您可以限定要修改的表的名称,或者从中获取信息:

alter schema.table ...
select ... from schema.table
Run Code Online (Sandbox Code Playgroud)

...

如果您开始在多台服务器上进行拆分,您仍然可以编写一些与多台服务器建立连接的脚本,以便您可以应用所有更改;同样,对于分析,您可以使用主数据库中的联合表设置一堆数据库链接,以便从一个地方访问数据,就像您只是从表中读取数据一样。

...

另外,请注意他们不是使用 mySQL 进行堆栈交换,而是使用 SQL Server。

而且我不知道在那种规模的 mysql 中会有什么样的性能开销,我认为我在 mysql 中从未超过 30 个“数据库”。


Rol*_*DBA 7

我有一个 Web/DB 托管客户端,它有 750 多个客户数据库,具有相同数量的表 (162) 和相同的表结构。加起来,我所有客户的客户数据总共 524GB(95% InnoDB)

想象一下,所有这些数据库都通过循环复制在 9 个数据库服务器上竞争 13G 的 innodb 缓冲池。使用该硬件配置进行横向扩展是不够的。我们立即向客户建议扩大规模。

我们最近将这个客户端迁移到了 3 个马力更大的数据库服务器(不惜一切代价,在高写入环境中远离 SSD,永远!!!)。我们将它们从 MySQL 5.0.90 升级到 MySQL 5.5.9。几乎立即就看到了戏剧性的差异。

还必须考虑横向扩展,因为如果您有数百个客户端使用相同的内存和磁盘资源,横向扩展会线性减少它们的使用量 (O(n)),其中 n 基于多主环境中的数据库服务器数量。

就我的客户而言,我的公司将他从 9 个 DB 服务器(Quad Code、32GB RAM、824G RAID10)减少到 MySQL 5.5 的更快 DB 服务器(Dual HexaCore [那是 12 个 CPU]、192GB RAM、1.7TB RAID10) .9(表利用多个 CPU)。此外,想象一下 50 个分区中的 150GB innodb 缓冲池,每个分区 3GB(多个 InnoDB 缓冲池是 MySQL 5.5 中的一个新特性)。较小的横向扩展,但大规模的扩展,适用于我客户的独特基础架构。

故事寓意:如果您的桌子设计得很糟糕,放大或缩小并不总是解决方案。我的意思是:如果索引页的多列索引键填充不平衡,从索引的不平衡部分查询键会导致表扫描后进行表扫描,或者至少由于被 MySQL 查询排除而从未使用过的索引优化器。正确的设计是无可替代的。

  • @EdCottrell 我猜这是关于 SSD 限制写入的警告。在某些时候,这会使驱动器磨损到无法再使用的程度,我相信在过去几年中,TRIM 和其他技术已融入 SSD 控制器芯片中以在很大程度上缓解这些问题,因此 SSD 写入虽然我确信它仍然可能是一个问题,但并不是什么大问题。 (4认同)
  • 我知道这真的很旧,但我想知道您对高写入环境中 SSD 的评论背后的推理是什么。你能启发我吗? (2认同)