租户隔离模型全景:独立数据库、共享Schema、共享表

在SaaS架构中,租户隔离模型决定了数据安全边界、资源分配粒度与运维复杂程度。三种经典模型——独立数据库、共享数据库独立Schema、共享表行级隔离——构成了多租户系统的核心选择谱系。理解它们的边界划分、组件职责与信任链路,是后续权限模型设计的前提。

三种经典租户隔离模型全景对比 接入层 / 路由层 独立数据库 租户 A 数据库 租户 B 数据库 租户 C 数据库 物理隔离 · 扩展性高 · 成本高 共享数据库独立Schema 共享数据库实例 Schema: tenant_a Schema: tenant_b Schema: tenant_c 逻辑隔离 · 运维中等 · 资源利用率高 共享表行级隔离 共享数据库实例 orders 表 TenantID=A, 订单1 TenantID=B, 订单2 TenantID=A, 订单3 行级隔离 · 成本低 · 扩展性好

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 落地步骤与验收标准

落地步骤:

  1. 确定租户身份识别机制(域名 / 子域名 / 请求头 X-Tenant-ID)。
  2. 基于当前业务阶段选择隔离模型,并预留迁移扩展点。
  3. 实现租户上下文传递中间件(Filter / Interceptor),将TenantID存入ThreadLocal。
  4. 在数据访问层强制注入隔离逻辑(MyBatis拦截器 / Hibernate Filter)。
  5. 编写针对跨租户访问的自动化渗透测试用例。

验收标准:

验收项独立数据库共享Schema共享表
数据隔离测试无法连接其他租户数据库无法查询其他Schema查询无法返回其他TenantID的行
性能隔离测试一个租户的慢查询不影响其他连接池饱和时所有租户受损需附加限流与降级措施
恢复演练单租户数据库恢复简单Schema级恢复,中间行级恢复复杂,依赖快照