如何创build共享表结构的多租户数据库?

我们的软件目前运行在MySQL上。 所有租户的数据存储在同一个模式中。 由于我们使用Ruby on Rails,所以我们可以很容易地确定哪些数据属于哪个租户。 但是,有些公司当然担心他们的数据可能会受到影响,所以我们正在评估其他解决scheme。

到目前为止,我看到了三个select:

  • 多数据库(每个租户都有自己的 – 每个客户的服务器几乎相同)
  • 多模式(在MySQL中不可用,每个租户都在共享数据库中获取自己的模式)
  • 共享模式(我们目前的方法,也许每个列都有额外的识别logging)

多架构是我最喜欢的(考虑成本)。 然而,创build一个新帐户并进行迁移似乎是相当痛苦的,因为我将不得不迭代所有模式并更改它们的表/列/定义。

问:多架构似乎被devise为每个租户有略微不同的表 – 我不想这样。 是否有任何RDBMS允许我使用多模式多租户解决scheme,其中表结构在所有租户之间共享?

PS多我的意思是像超多(10.000 +租户)的东西。

但是,有些公司当然担心他们的数据可能会受到影响,所以我们正在评估其他解决scheme。

这是不幸的,因为客户有时会有一种误解,认为只有物理隔离才能提供足够的安全性。

有一个有趣的MSDN文章,标题为多租户数据架构 ,您可能要检查。 这就是作者如何解决对共享方法的误解:

一个常见的误解认为,只有物理隔离才能提供适当的安全级别。 实际上,使用共享方式存储的数据也可以提供强大的数据安全性,但需要使用更复杂的devise模式。

至于技术和商业方面的考虑,文章简要分析了某种方法可能比另一种方法更合适:

您希望服务的租户的数量,性质和需求都会以不同的方式影响您的数据架构决策。 下面的一些问题可能会使你偏向一个更孤立的方法,而另外一些问题可能会使你偏向一个更加共同的方法。

  • 你预计有多less潜在租户? 你可能远远没有能够用权威估计未来的使用情况,但是从数量的angular度来看,你是在为数百个租户build立一个应用程序吗? 成千上万的? 成千上万? 更多? 您预计租客基数越大,您就越有可能考虑采用更为共享的方法。

  • 您预计平均租户的数据占用了多less存储空间? 如果您希望部分或全部租户存储大量数据,那么单独数据库方法可能是最好的。 (实际上,数据存储需求可能会迫使你采用单独的数据库模型,如果这样的话,从一开始就devise应用程序要容易得多,而后来转向单独的数据库方法)。

  • 你预计平均租户支持多less个并发最终用户? 数量越大,更合适的更孤立的方法将是满足最终用户的要求。

  • 您是否期望提供任何每租户增值服务,例如每租户备份和恢复function? 这种服务更容易通过更独立的方式提供。


更新:进一步更新关于预计租户数量。

如果不是所有的情况,预期的租户数量(10万)应该排除多数据库方法。 我不认为你会喜欢维护10,000个数据库实例的想法,并且每天都必须创build数百个新实例。

单从这个参数看来,共享数据库,单一模式方法是最合适的。 事实上,你将每个租户存储大约50Mb,并且不会有每个租户的附加组件,这使得这种方法更加合适。

上面引用的MSDN文章提到了三个安全模式,解决共享数据库方法的安全考虑:

  • 受信任的数据库连接
  • 租户查看filter
  • 租户数据encryption

当您对应用程序的数据安全措施有信心时,您将能够为您的客户提供一个服务级别Agrement ,提供强大的数据安全保证。 在您的SLA中,除了保证之外,您还可以描述为确保数据不受影响而采取的措施。

我的经验(尽pipeSQL Server)是多数据库是要走的路,每个客户端都有自己的数据库。 所以,虽然我没有MySQL或Ruby On Rails的经验,我希望我的input可能会增加一些价值。

原因包括:

  1. 数据安全/灾难恢复。 每个公司的数据都完全独立于其他数据存储,从而降低了数据受到攻击的风险(思考如果引入了代码错误,这意味着某些错误地查看其他客户数据的情况),最大限度地减less一个客户的潜在损失特定的数据库被破坏等等。对客户的安全效益甚至更大(额外的奖励副作用!)
  2. 可扩展性。 从本质上讲,你可以将数据划分出来以实现更好的可扩展性 – 例如,数据库可以放在不同的磁盘上,可以使多个数据库服务器联机并使数据库更容易分散负载。
  3. 性能调整。 假设你有一个非常大的客户端和一个非常小的客户端。 使用模式,数据量等可以大不相同。 您可以根据需要调整/优化每个客户。

我希望这确实提供了一些有用的input! 还有更多的原因,但是我的脑子里一片空白。 如果它踢回来,我会更新:)

编辑:
自从我发布这个答案以来,现在很清楚我们正在谈论10,000多个租户。 我的经验是在数以百计的大型数据库中 – 我不认为10,000个独立的数据库对您的情况来说太可pipe理,所以我现在不喜欢您的scheme中的多数据库方法。 特别是现在很清楚,你正在为每个租户谈论小数据量!

保持我的答案在这里,因为它可能有一些类似的船(使用较less的租户)

以下是Salesforce.com上关于如何实施多租户的白皮书的链接:

media/ForcedotcomBookLibrary/Force.com_Multitenancy_WP_101508.pdf

他们有1个巨大的表w / 500个string列(Value0,Value1,… Value500)。 date和数字以一种格式存储为string,以便在数据库级别将其转换为本机types。 有元数据表定义数据模型的形状,每个租户可以是唯一的。 还有额外的索引表,关系,唯一值等

为什么麻烦?

每个租户都可以在运行时自定义自己的数据模式,而无需在数据库级别进行更改(更改表等)。 这绝对是这样做的难办法,但非常灵活。

正如你所提到的,每个租户的一个数据库是一个select,并有一些更大的权衡。 它可以在较小的规模下工作,比如单个数字或者低10的租户,但是除此之外,它变得更难以pipe理。 无论是只是迁移,但也只是保持数据库的运行。

每个模式模型不仅对每个模式有独特的模式有用,尽pipe仍然在所有租户之间迁移变得困难,并且在1000个模式下Postgres可能开始有麻烦。

更可扩展的方法绝对是将租户随机分布,存储在同一个数据库中,但跨越不同的逻辑分片(或表 )。 根据你的语言,有一些库可以帮助你。 如果您使用的是Rails,那么在租户acts_as_tenant有一个库,这有助于确保您的租户查询只能撤回该数据。 还有一个gemapartment – 虽然它使用了模式模型,但它有助于跨所有模式的迁移。 如果你使用的是Django,那么有一个数字,但是更受欢迎的模式之一似乎跨越了模式 。 所有这些在应用程序级别上帮助更多。 如果您直接在数据库层面上寻找更多的东西, Citus专注于使Postgres开箱即可使用这种分租方式进行多租户工作。