3、数据隔离策略:独立数据库模式、共享数据库独立Schema模式、共享数据库共享表模式、混合模式选型
数据隔离,说白了就是怎么把不同租户的数据「隔开」。
这个问题我当年刚做多租户系统时,踩过不少坑。有一次客户投诉说看到了别人的订单数据,吓得我连夜改方案。嗯,从那以后,我对数据隔离策略就特别敏感。
目前主流的方案有四种:独立数据库、共享数据库独立Schema、共享数据库共享表、以及混合模式。咱们一个一个聊。
3.1 独立数据库模式
每个租户一个独立的数据库实例。这是最「硬核」的隔离方式。
核心特点:
- 物理隔离,数据安全性最高
- 备份恢复互不影响
- 可针对大租户单独做性能调优
- 成本最高,管理最复杂
我在项目中遇到过一个大客户,月活用户上千万,数据量几十TB。这种场景下,独立数据库几乎是唯一选择。你想想看,如果跟其他小租户挤在一起,一个慢查询就能拖垮所有人。
适用场景:
- 金融、医疗等强监管行业
- 超大型租户(数据量 > 100GB)
- 对SLA有严格要求的客户
3.2 共享数据库独立Schema模式
同一个数据库实例,但每个租户拥有独立的Schema(命名空间)。
我个人习惯把这个模式叫做「逻辑隔离」。所有租户共用数据库连接池,但表结构是分开的。
| 对比项 | 独立数据库 | 共享Schema |
|---|---|---|
| 隔离级别 | 物理隔离 | 逻辑隔离 |
| 成本 | 高 | 中 |
| 扩展性 | 好 | 一般 |
| 管理复杂度 | 高 | 中 |
我曾经帮一个SaaS平台做过架构改造。他们一开始用共享表模式,结果租户之间数据互相污染。后来改成独立Schema,问题就解决了。其实对于大多数中小型租户,这个模式性价比最高。
注意:Schema数量过多时,数据库元数据管理会成为瓶颈。我建议单个实例不要超过500个Schema。
3.3 共享数据库共享表模式
所有租户共用同一套表,通过租户ID字段(tenant_id)来区分数据。
说白了,这就是最「省钱」的方案。但也是最容易出问题的方案。
-- 典型的共享表结构
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
tenant_id VARCHAR(32) NOT NULL,
order_no VARCHAR(64),
amount DECIMAL(10,2),
created_at DATETIME,
-- 所有租户共用
INDEX idx_tenant_id (tenant_id)
);
这里有个坑:所有查询都必须带上tenant_id条件。我见过一个团队忘了加这个条件,结果A租户的报表里出现了B租户的数据。嗯,那场面相当尴尬。
避坑指南:
- ORM层强制注入tenant_id过滤条件
- 数据库层面做行级安全策略(RLS)
- 定期做数据完整性校验
3.4 混合模式
实际项目中,很少只用一种模式。我建议的做法是:按租户等级混合使用。
举个例子,我之前设计的一个低代码平台:
- 免费版租户:共享表模式,降低成本
- 专业版租户:独立Schema模式,保证性能
- 企业版租户:独立数据库模式,满足合规
你想想看,如果所有租户都用独立数据库,小租户根本付不起那个钱。反过来,如果大租户也用共享表,性能和安全都扛不住。
混合模式的核心原则:
- 根据租户付费等级决定隔离级别
- 支持租户升级时平滑迁移数据
- 统一的数据访问层,屏蔽底层差异
3.5 选型决策矩阵
我整理了一个决策表,方便你快速判断:
| 评估维度 | 独立数据库 | 独立Schema | 共享表 |
|---|---|---|---|
| 数据安全性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| 运维成本 | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 扩展性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| 适合租户规模 | 大 | 中 | 小 |
最后提醒一句:选型没有银弹。我见过太多团队一开始选共享表,后来数据量大了再迁移,那叫一个痛苦。建议一开始就预留好升级路径。
好了,数据隔离策略就聊到这儿。下一章咱们讲讲多租户下的缓存设计,那个坑更多,到时候我慢慢说。