租户隔离模型全景:独立数据库、共享Schema、共享表
在SaaS架构中,租户隔离模型决定了数据安全边界、资源分配粒度与运维复杂程度。三种经典模型——独立数据库、共享数据库独立Schema、共享表行级隔离——构成了多租户系统的核心选择谱系。理解它们的边界划分、组件职责与信任链路,是后续权限模型设计的前提。
2.1 边界与分层定义
三种模型的本质区别在于信任边界所处的位置不同:
- 独立数据库:边界位于数据库实例层面,网络层与操作系统层天然隔离,一个租户的攻击面无法影响其他租户。
- 共享数据库独立Schema:边界下沉至数据库内部Schema,依赖数据库元数据隔离机制。
- 共享表行级隔离:边界退化为应用层强制的行级TenantID过滤,考验的是数据访问层的代码质量。
2.2 组件职责与数据流
| 隔离模型 | 路由层职责 | 数据访问层职责 | 数据流路径 |
|---|---|---|---|
| 独立数据库 | 动态数据源路由,分配对应租户的连接池 | 管理每个租户独立的JDBC连接 | App → 路由层 → 租户特定数据库 |
| 共享Schema | 解析租户上下文,设置当前Schema | 通过search_path限定表空间 | App → 路由层 → 共享数据库 → 租户Schema |
| 共享表 | 提取并传递租户ID(JWT/Header) | 通过拦截器/过滤器自动追加WHERE tenant_id=? | App → 路由层 → 共享数据库 → 租户行 |
2.3 选型权衡:SaaS成熟度映射
決策矩阵:初创期选择共享表以快速上线、降低成本;成长期过渡到共享Schema以增强数据安全;大型企业级服务升级为独立数据库以获得物理级隔离。三种模型并非互斥,在一个成熟SaaS平台中常以混合形态存在(如铂金租户独享数据库、标准租户共享表)。
2.4 风险点
- 独立数据库:硬件资源利用率低,备份窗口长,需要更复杂的数据库运维自动化。
- 共享Schema:连接池争用导致“吵闹邻居”效应;DDL变更影响所有租户Schema。
- 共享表:最大的风险来自应用层漏洞——在SQL中遗漏TenantID过滤即可能导致跨租户数据泄露,必须通过在数据层强制注入与渗透测试进行兜底。
2.5 落地步骤与验收标准
落地步骤:
- 确定租户身份识别机制(域名 / 子域名 / 请求头 X-Tenant-ID)。
- 基于当前业务阶段选择隔离模型,并预留迁移扩展点。
- 实现租户上下文传递中间件(Filter / Interceptor),将TenantID存入ThreadLocal。
- 在数据访问层强制注入隔离逻辑(MyBatis拦截器 / Hibernate Filter)。
- 编写针对跨租户访问的自动化渗透测试用例。
验收标准:
| 验收项 | 独立数据库 | 共享Schema | 共享表 |
|---|---|---|---|
| 数据隔离测试 | 无法连接其他租户数据库 | 无法查询其他Schema | 查询无法返回其他TenantID的行 |
| 性能隔离测试 | 一个租户的慢查询不影响其他 | 连接池饱和时所有租户受损 | 需附加限流与降级措施 |
| 恢复演练 | 单租户数据库恢复简单 | Schema级恢复,中间 | 行级恢复复杂,依赖快照 |