如何设计多租户mysql数据库

ddarikpa  于 2023-01-01  发布在  Mysql
关注(0)|答案(7)|浏览(303)

假设我需要设计一个数据库来存放多个公司的数据,现在为了安全和管理的目的,我需要确保不同公司的数据被适当地隔离,但是我也不想启动10个mysql进程来存放10个公司在10个不同的服务器上的数据,用mysql数据库做这件事的最好方法是什么?

qxsslcnc

qxsslcnc1#

多租户数据库有几种方法,为了便于讨论,通常将它们分为三类。

  • 每个租户一个数据库。
  • 共享数据库,每个租户一个模式。
  • 共享数据库,共享模式。承租人标识符(承租人键)将每一行与正确的承租人相关联。

MSDN上有一篇关于pros and cons of each designexamples of implementations的好文章。
微软显然已经删除了我提到的页面,但它们在archive.org上。链接已改为指向那里。
这是第二篇文章的原始链接,仅供参考

iecba09b

iecba09b2#

在MySQL中,我更喜欢对所有租户使用一个数据库,我通过对每个租户使用一个单独的数据库用户来限制对数据的访问,该用户只能访问只显示属于该租户的行的视图。
这可以通过以下方式实现:
1.向每个表添加tenant_id列
1.使用触发器在插入时用当前数据库用户名填充tenant_id
1.为其中tenant_id = current_database_username的每个表创建一个视图
1.仅使用应用程序中的视图
1.使用租户特定的用户名连接到数据库
我在一篇博客文章中对此进行了充分的记录:https://opensource.io/it/mysql-multi-tenant/

qyyhg6bp

qyyhg6bp3#

简单的方法是:为每个共享表添加一列SEGMENT_ID,为每个客户分配合适的SEGMENT_ID,然后根据SEGMENT_ID为每个客户创建视图,这些视图将数据与每个客户分开,通过这种方法,信息可以共享,使操作和开发都变得简单(存储过程也可以共享)。

umuewwlo

umuewwlo4#

假设您在一个MySQL示例上运行一个MySQL数据库-有几种方法可以区分哪些数据属于谁,最明显的选择(至少对我来说)是创建一个复合主键,如下所示:

CREATE TABLE some_table (
id int unsigned not null auto_increment,
companyId int unsigned not null,
..
..
..,
primary key(id, company_id)
) engine = innodb;

然后通过更改主键的companyId部分来区分公司。这样,您可以将所有公司的所有数据放在同一个表/数据库中,并且在应用程序级别可以控制哪个公司与哪个companyId绑定,并确定为某个公司显示哪些数据。
如果这不是你想要的-我很抱歉误解了你的问题。

j2qf4p5b

j2qf4p5b5#

您是否考虑过为每家公司创建不同的schema
不过,你应该试着更准确地定义你想要实现的目标。
例如,如果您希望确保一个硬件故障不会危及多个公司的数据,则必须创建不同的示例并在不同的节点上运行它们。
例如,如果您要确保公司A的某个人无法看到属于公司B的数据,则可以按照Matthew PK的答案在应用程序级别执行此操作
但是,如果您想确保有人设法危害安全性并对DB运行任意SQL,则需要比这更健壮的东西。
如果您希望能够独立备份数据,以便可以在星期一安全地备份C公司的数据,在星期日安全地备份A公司的数据,并且能够仅恢复C公司的数据,那么,纯粹基于应用程序的解决方案同样无济于事。

yr9zkbsy

yr9zkbsy6#

给定一个特定的DB用户,您可以将用户成员资格赋予组,以指示允许他们访问其数据的公司。
我假设您将有一个Companies表,因此只需在CompaniesMySQLUsers之间创建一个一对多关系或类似的关系。
然后,作为所有查询的条件,只需根据UserID匹配CompanyID

lsmepo6l

lsmepo6l7#

在我的文件Generate_multiTanentMysql. php中,我使用PHP脚本执行所有步骤
https://github.com/ziedtuihri/SaaS_Application

解决方案设计模式:

  • 为每个租户创建数据库用户
  • 将每个表重命名为不同且唯一的名称(例如,使用前缀“someprefix_”)
  • 向每个表添加一个名为“id_tenant”的文本列,以存储该行所属的承租人的名称
  • 为每个表创建一个触发器,以便在插入新行之前自动将当前数据库用户名存储到id_tenant列
  • 使用原始表名为每个表创建一个视图,该表包含除id_tenant之外的所有列。该视图将仅返回其中(id_tenant = current_database_username)
  • 只向每个租户的数据库用户授予视图(而不是表)的权限。然后,应用程序唯一需要更改的部分是数据库连接逻辑。当有人连接到SaaS时,应用程序需要:
  • 以租户特定的用户名连接到数据库

相关问题