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


48

我记得在stackoverflow播客中,Fog Creek为每个客户使用了一个数据库,用于Fogbugz。我认为这意味着Fogbugz On Demand服务器具有成千上万个数据库。

我们才刚刚开始开发Web应用程序,并且有类似的问题要解决(很多拥有自己孤立数据的客户)。

我对每个客户使用数据库有什么问题?我该如何解决?

我的初步想法

每个客户的数据库优势

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

缺点

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

2
请记住,“数据库”对不同的人来说意味着不同的事情。在Oracle世界中,每个用户的数据库将是巨大的杀伤力。但是在MySQL中,“数据库”与“模式”是同义词。
盖乌斯,

我的意思是mysql。USE CompanyData;
Rik Heywood

1
Microsoft有一篇有关多租户数据体系结构的详细文章。
Nick Chammas

我不会说对模型进行版本控制是不利的...更多的工作,但是总体上更好
Neil McGuigan

Answers:


40

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

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

具有单独的数据库确实意味着您必须建立一种更新机制,以使数据库版本与应用程序/站点版本匹配。但是,单独的数据库确实提供了出色的数据隔离,并且IMO的托管成本较低。并非所有情况都适用。如果您的系统永远不会在托管范围之外托管,并且需要快速扩展客户规模,并且希望所有用户使用相同版本的应用程序和数据库架构,那么肯定有一个数据库是更好的方法。


2
我同时使用共享数据库和多租户单独的数据库设置来运行Web服务。有时候两者都是正确的选择。在每个客户都有一个单独数据库的应用程序上,我遇到了完全相同的5个原因,这是该应用程序的正确选择。
Dan Grossman

亚马逊最近的Aurora无服务器云数据库据说可以在需要更高负载时自动调配更多资源,而且它们似乎鼓励单数据库设计。但是我不完全理解。我想我将使用单个数据库,但为每个用户使用单独的表。如果需要的话,这可能会更容易将它们拆分为单独的数据库,并使对所有用户数据的聚合查询更加容易。
Buttle Butkus

只是需要提防的事情:我将所有客户都放在一个数据库中,并且使用数据库代码层来确保每个查询都包含客户特定条件。危险的一面是,当您必须走出数据库层以执行非常特定的操作时-例如可怕的大型复杂查询,其中数据可能会从意外地方泄漏出去。
谜加

14

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

去年,我使用了70个数据库(远远少于5000个),每个数据库都具有相同的架构。从理论上讲,事情会按计划进行(如您在“优势”部分中提到的),但实际上并没有那么多。您有很多关于更新架构,用户支持,软件更新的问题。太可怕了

我们使用Firebird,并且在产品出厂后就被录用了,但是这使我掌握了从不使用单独数据库的知识。

我并不是说您无法实现目标,而是说事情可能会变得非常错误,老实说,您的优势列表听起来并不足以吸引风险。其中大多数可以通过单个数据库完成。


我们实现了为多个客户提供服务的多重列表数据库。在客户开始想要自定义结果的情况下,我们陷入困境。为了解决此问题,我们克隆了存储的proc,并为其赋予了唯一的客户名称前缀,然后从应用程序内部对其进行了调用。另一方面,我们售出了150个网店,每个网店都有各自独立的数据库(97%相同)。因此,这两种情况都可以完成,具体取决于情况。
迈克尔·赖利

真好 我并不是说这不可能完成,只是它听起来并不简单,对您来说对Gunny有好处。
eiefai 2011年

1
如果您可以举出错误原因的示例,那就太好了。当然,要使所有数据库保持最新是很困难的,但是要决定我们必须能够衡量优缺点。
鲍里斯·卡伦斯

9

您可能希望保留另一个数据库来跟踪每个客户所处的版本,因此您可以跟踪哪些客户已经或未进行最后一轮修改。

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

正如Gaius指出的那样,由于mysql的“数据库”只是架构,如果它们都在同一服务器实例上运行,则可以限定要修改的表的名称,或者从以下信息中获取信息:

alter schema.table ...
select ... from schema.table

...

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

...

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

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


为什么不在数据库本身中保留版本信息表?
鲍里斯·卡伦斯

@Boris:因为当您有数十个或数百个数据库时,要连接到每个数据库以要求提供其版本会比较麻烦。每个人都可以跟踪自己,这不是一个坏主意,但是拥有一个DBA主列表也很值得

7

我有一个Web / DB Hosting客户端,该客户端具有750多个客户数据库,这些数据库具有相同数量的表(162)和相同的表结构。总的来说,我客户的所有客户数据总计524GB(95%的InnoDB)

想象一下,所有这些数据库都通过循环复制在九台数据库服务器上争夺13G innodb缓冲池。仅凭该硬件配置进行扩展还不够。立即,我们建议客户扩大规模。

最近,我们将此客户端迁移到了功能更强大的3个DB服务器上(不惜一切代价,请远离高写入环境中的SSD,始终如此!)。我们将它们从MySQL 5.0.90升级到MySQL 5.5.9。几乎立即就可以看到戏剧性的差异。

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

对于我的客户,我的公司正在将他的数量从MySQL 5.5的9个数据库服务器(Quad Code,32GB RAM,824G RAID10)减少到更快的数据库服务器(Dual HexaCore [即12个CPU],192GB RAM,1.7TB RAID10)。 .9(要利用多个CPU来发挥作用)。此外,想象一下在50个分区(每个分区3GB)中有150GB的innodb缓冲池(多个InnoDB缓冲池是MySQL 5.5中的一项新功能)。规模较小但规模较大的扩展已为我客户的独特基础结构提供了帮助。

故事的寓意:如果表的设计不正确,则放大或缩小并非总是解决方案。我的意思是:如果索引页面的多列索引的键填充不平衡,则从索引的不平衡部分查询键会导致表扫描后进行表扫描,或者至少由于MySQL Query的排除而无法使用的索引优化器。根本没有替代适当设计的方法。


2
我知道这确实很老,但是我想知道您对高写入环境中的SSD的评论背后的原因是什么。你能启发我吗?
elixenide 2015年

4
@EdCottrell我的猜测是这是有关SSD有限写入的警告。在某种程度上,这会使驱动器磨损到无法使用的程度,我相信在过去的几年中,TRIM和其他技术已被应用到SSD控制器芯片中,以在很大程度上缓解这些问题,因此SSD写入尽管我确信这仍然是一个问题,但它并没有太大的问题。
shaunhusain '16

2

MySQL在单独的目录中创建数据库,因此很大程度上取决于基础操作系统以及它可以处理的文件夹/文件处理数量。对于现代操作系统而言,这不应该是一个问题,但这是许多瓶颈的来源。


1

没有任何内容表明您必须托管不同版本的数据库或应用程序。仅通过为每个客户分配一个db并拥有一个版本的数据库和应用程序来简单地隔离数据有什么问题?当然,每个客户数据库都必须从当前工作版本的模板中克隆。从安全和数据隔离的角度来看,我认为这是理想的。

我唯一看到的缺点是,在创建新版本时,您将必须手动更新每个数据库。不过,这很容易实现自动化。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.