› MySQL 5.5 Community Server
› MySQL 5.6 Community Server
› Percona Configuration Wizard
› XtraBackup 搭建主从复制
Great Sites on MySQL
› Percona
› MySQL Performance Blog
› Severalnines
推荐管理工具
› Sequel Pro
› phpMyAdmin
推荐书目
› MySQL Cookbook
MySQL 相关项目
› MariaDB
› Drizzle
参考文档
› http://mysql-python.sourceforge.net/MySQLdb.html
lostSoul
V2EX  ›  MySQL

多租户系统,采用 PostgreSQL 好还是 Mysql 好

  •  1
     
  •   lostSoul · May 11, 2021 · 10481 views
    This topic created in 2007 days ago, the information mentioned may be changed or developed.

    saas 类型的系统,目前是采用了最 low 的行级多租户,也就是每个表加一个 tenantId,然后用代码逻辑隔离,现在随着系统的用户增长,很多问题随着出现了,维护麻烦,性能低效,代码逻辑复杂混乱
    于是决定重构,打算采用多租户的另外一套方案,单库多 schema,但查阅了资料,发现 mysql 根本没有真正意义上的 schema,或者说 schema 就是 database
    再后来了解到 PostgreSql,感觉国内资料挺少的,用的也很少,但看到一些比较资料发现他比 mysql 好太多了,但又怕上了踩坑,而且还要数据迁移之类的,有没有大佬给个方案

    Supplement 1  ·  May 11, 2021
    我这边总结了几个方案,先说说传统的解决方案:
    数据隔离有三种方案:
    1 、独立数据库:简单来说就是一个租户使用一个数据库,这种数据隔离级别最高,安全性最好,但是提高成本。
    2 、共享数据库、隔离数据架构:多租户使用同一个数据裤,但是每个租户对应一个 Schema(数据库 user)。
    3 、共享数据库、共享数据架构:使用同一个数据库,同一个 Schema,但是在表中增加了租户 ID 的字段,这种共享数据程度最高,隔离级别最低。

    目前我的系统采用了最 low 的第三个方案,我是强烈不推荐这个方案,迫不得已才用它,因为他只会加重数据的维护难度和让代码变得异常复杂,我是使用了 myabtis 的插件来拦截,但是当一些场景复杂后你的 SQL 不得不吐血

    所以我把矛头指向了 postgreSql,因为他天生就自带支持多个多租户的方案,但因为国内资料少,坑多,数据迁移也是问题,故无法采用。

    最后我决定采用 Mysql + MyCat (中间件,基于阿里开源的 cobar 演变而来)+Mybatis,之所以采用 MyCat,因为他提供了多租户的解决方案,同时增强了 mysql 的处理性能了,最重要的是 mycat 更新也很社区活跃算是可以,同时提供了丰富的文档
    Supplement 2  ·  May 11, 2021
    有更好的解决方案欢迎大佬提出,感谢!
    Supplement 3  ·  May 12, 2021
    感谢各位大佬的回复,评论很多说第三套方案不 low,其实我要表达的不是单单的 low,而是想表达太简单粗暴,后面我想了想,也对,三个方案其实都好,但是要结合实际出发


    首先是如何选择方案,主要考虑的首先是安全和成本,安全决定了隔离级别
    我们应该从多个方面来选择方案,而不是哪个方案 low 不 low

    首先考虑成本,1 块钱掰成两份花,隔离越低则成本越低,相对维护成本也会下降,但安全性也会随之下降。

    其次是安全因素:要考虑业务和客户的安全方面的要求。安全性要求越高,越要倾向于隔离。

    所以必须从多个方面去考虑:
    39 replies  •  2025-04-22 19:15:54 +08:00
    czyt
    czyt
    May 11, 2021
    1
    有迁移数据库的需求,建议开发的时候用 orm
    ez728s
    ez728s
    May 11, 2021
    2
    怕不是因为方案 low
    xiaoxinshiwo
    xiaoxinshiwo
    May 11, 2021
    3
    淘宝算不算多租户系统?
    lostSoul
    lostSoul
    OP
    May 11, 2021
    4
    @ez728s 就是因为方案 low 才改的 我现在已经想到另外一方案 采用 Mysql+MyCat 中间件,采用 mycat 去增强 mysql 的功能,mycat 中间件提供了多租户方案,实现 SQL 方式切换数据源
    emmettwoo
    emmettwoo
    May 11, 2021
    5
    插眼等老哥们的方案,这种用数据库字段隔离然后代码去判断真的太难受了。
    312ybj
    312ybj
    May 11, 2021❤️1
    6
    我们公司的数据隔离级别就是单独 schema, 使用 myact 拦截 sql,从而导向不同的数据库。redis 也这样干的。
    BQsummer
    BQsummer
    May 11, 2021
    7
    租户 id 放 theadlocal,自定义个 mybatis 插件,自动补全租户 id 的查询条件,在业务层面不需要额外处理租户的信息,还是体验可以的。好处是数据库层可以简单化,没啥 low 不 low 的。
    wangxiaoaer
    wangxiaoaer
    May 11, 2021❤️1
    8
    ”现在随着系统的用户增长,很多问题随着出现了,维护麻烦,性能低效,代码逻辑复杂混乱“

    租户表示我不背这个锅。
    johnsona
    johnsona
    May 11, 2021 via iPhone
    9
    @emmettwoo 判断 tenantid 是吧
    orm 的方案的话可以 hook 一下自动带上 tenantid
    FightPig
    FightPig
    May 11, 2021❤️1
    10
    不建议 schema 模式,tenantId 模式挺好的,schema 随着用户多起来,你会发现很头疼,如果你再有要查询多租户信息的需求,你就要崩溃了
    lostSoul
    lostSoul
    OP
    May 11, 2021
    11
    @wangxiaoaer 哈哈 不被也得背啊 没办法 现在新建一个商户 虽然他看不到其他租户的数据 但都等于他有 100W 条数据了 大家同一条船迟早都得淹死
    lostSoul
    lostSoul
    OP
    May 11, 2021
    12
    @FightPig 查询多租户需求也是可以满足的吧 我目前这个方案而言 我们已经用血的教训证明 tenantId 并不是长久方案
    keenkiller
    keenkiller
    May 11, 2021❤️1
    13
    你这个思路好奇怪…而且这都 2021 年了,还有人用 Mycat ?

    你直接上 tidb 啊……当然 pg 生态也有 greenplum 之类的
    Huiao
    Huiao
    May 11, 2021
    14
    单数据库 多租户表 表名:business_{租户 id} mybatis 插件动态补全表名
    love
    love
    May 11, 2021❤️3
    15
    为什么 tenantId 是最 low 的方案?能列个实际的代码例子吗,我以前的公司也这样,我感觉是最高级的方案,一点不觉得不方便。
    反而一个用户一个数据库才是 low 到爆的方案,维护复杂更不用提了
    ipwx
    ipwx
    May 11, 2021❤️1
    16
    我直觉上,tenantId 是很好的方案。但是得配合分库分表,通过 tenantId 哈希到某个机器的数据库上,每个机器上又存储若干 tenantId 的数据。如果之前的数据库满了就增加机器,哈希函数改一改。如果某个租户变成狗大户就专门给他放到狗大户的机器上,狗大户的机器少放点租户,小用户的机器上多放点用户。
    wangxiaoaer
    wangxiaoaer
    May 11, 2021
    17
    @FightPig #10 楼上有老哥提到淘宝,你说这算不算多租户呢,刚开始我还没觉得,但是一细想,也算多租户,每个商家就是一个租户,维护自己的产品。难道这些产品分别放到不同的库里才是优雅?

    你说全部放到一起量大起来迟早淹死,可是我寻思面对这个问题你应该寻求的是海量数据存储、检索的方案,这些应该成熟的吧,什么 nosql 、分布式不行吗?

    另外,我觉得 tenantId (其实就是特么的 UserID 了)方案还有个好处:当后面需要做跨租户统计、分析的时候,明显要比多租户方便吧。
    hbkdsm
    hbkdsm
    May 11, 2021❤️1
    18
    不同意逻辑隔离是最 low 的方案,这是最高效的方案 (虽然牺牲了数据隔离性)

    多 db 和 多 schema 维护成本太高了,大表跑 DDL 痛苦死了
    Salesforce 就是 tenantID 纯逻辑隔离,Zendesk, Freshdesk, GitHub 都是这样
    这是业内最成熟的方案

    库大了,还可以根据 tenantID 做水平分库,PostgreSQL 有 Citus,MySQL 有 ShardingSphere,都可以按照 tenantID 分库。

    还有 TiDB 这种 NewSQL,或者 Vitess 这种方案。
    BBCCBB
    BBCCBB
    May 11, 2021
    19
    @hbkdsm Big old, 这些系统得 tenantId 是哪里看的?
    dbskcnc
    dbskcnc
    May 11, 2021
    20
    用的 PostgreSql 的话还可以继续用原来的方案的,表针对 tenantID 做 hash 分区,性能和开发都方便
    用中间件感觉还是有点折腾,有条件当然可以上 newsql
    miao1007
    miao1007
    May 11, 2021
    21
    万事不绝,ELK 包治百病,用 ELK 索引作为二级主键
    zzl22100048
    zzl22100048
    May 11, 2021
    22
    元数据驱动模式做 saas 不是更好么
    zieglar
    zieglar
    May 11, 2021
    23
    PostgreSQL 做错了什么要把矛头指向它(
    joesonw
    joesonw
    May 11, 2021
    24
    其实这种场合 sqlite 很合适.
    AngryPanda
    AngryPanda
    May 11, 2021 via iPhone
    25
    我们 mongodb 分 db 方案
    xuanbg
    xuanbg
    May 11, 2021
    26
    第三种增加据的维护难度和让代码变得异常复杂???我怎么一点感觉都无?哦哦,我是手写 SQL,无非就是查询条件增加一个 tenantId = #{tenantId}的条件而已。没事了没事了。
    kaneg
    kaneg
    May 12, 2021 via iPhone
    27
    table 加 tennat id 如果能在框架层面做还好。否则纯手动维护,如果碰到粗心的程序员在某些语句中忘了加 tenant id,那后果就不可设想了。在某个项目中碰到过这样的案例:开发在本地测试的时候只有一个 tenant,没有测出这个问题。结果在项目上线后被客户发现看到了其他公司的数据。。。
    sss007
    sss007
    May 12, 2021
    28
    我们系统用 sqlserver 五年了快,就是 low3 方案,加了个 compid
    securityCoding
    securityCoding
    May 12, 2021
    29
    tennat id 不是挺好的吗?
    HashV2
    HashV2
    May 12, 2021
    30
    哪有什么 low 不 low 的 只看使用场景和需求 能满足的需求的设计就是好设计
    ccppgo
    ccppgo
    May 12, 2021
    31
    什么意思, 如果有上万个用户就有上万个库吗,,,
    notejava
    notejava
    May 12, 2021
    32
    通过租户 ID 进行数据隔离才是最简单,最好扩展的方案。我目前项目也遇到一模一样的场景。
    lostSoul
    lostSoul
    OP
    May 12, 2021
    33
    1.租户处于爆发式增长应该越倾向于共享,因为一旦租户多了起来,不管是单库还是单表多 schema,维护的成本都是巨大的,涉及后期迭代的时间成本也会随即累加(场景:一些对外开放的 Saas 系统,支持用户自主注册使用,而非人工开通或付费开通)
    lostSoul
    lostSoul
    OP
    May 12, 2021
    34
    2.租户数量平稳同时租户数据多应该倾向于隔离,使用隔离级别高的有利于对每个租户进行定制化开发而不会影响到其他租户
    lostSoul
    lostSoul
    OP
    May 12, 2021
    35
    因为我是新号回复受限只能回复在评论里
    oneforallsoft
    oneforallsoft
    May 12, 2021
    36
    @lostSoul
    而且如果租户有各种各样的需求 每个租户都不一样 就应该一个租户一个数据库 一个租户一套代码
    不会互相影响 尤其是在没有足够测试人员的情况下
    solos
    solos
    May 12, 2021
    37
    这不是很正常,现在有 tidb / cockroach 这些支持水平扩展的分布式数据库了,更不是问题了
    ccde8259
    ccde8259
    May 12, 2021 via iPhone
    38
    MySQL 有分区表……
    直接拿 tenantId 做 Column Partition 就避免发生新租户上来就在查百万表的情况……
    同时 5.7 开始支持索引条件下推……
    qbmiller
    qbmiller
    Apr 22, 2025
    39
    @kaneg 阿里云盘
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1465 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 76ms · UTC 10:15 · PVG 18:15 · LAX 02:15 · JFK 05:15
    ♥ Do have faith in what you're doing.