在构建 SaaS 平台时,数据隔离策略直接决定了系统的安全性、扩展性以及运维成本。随着租户数量的增长,初期选择的架构往往会面临性能瓶颈或管理上的挑战。在关系型数据库(尤其是 PostgreSQL)的生态中,Schema 级别隔离和行级安全(Row-Level Security, RLS)是两种最典型的实现路径。
Schema 隔离的做法是为每个租户创建一个独立的 Schema。这种模式下,数据在逻辑上是完全分开的,应用程序通过在建立数据库连接或执行查询前动态切换 search_path 来路由到目标租户。这种架构的安全边界清晰,且不同租户的数据备份与恢复操作可以独立进行,非常适合合规要求较高的场景。然而,当租户数量突破千级别时,数据库中的表数量会呈指数级增长,导致元数据膨胀,不仅拖慢了 DDL 变更的速度,还会对连接池的管理造成压力。
相对而言,基于 RLS 的共享表架构通过在每张表上增加一个 tenant_id 字段来区分数据。PostgreSQL 原生支持在表上定义策略(Policy),在查询执行时自动追加租户过滤条件。这种方式极大地简化了 Schema 的管理,所有租户共享同一套表结构,数据库对象数量保持在极低的水平,系统的连接复用率也很高。
在实践中,采用 RLS 方案需要特别关注查询性能。每一次查询都会隐式附加租户条件,这意味着绝大多数查询的执行计划都会发生改变。为了避免全表扫描,索引的设计必须将 tenantid 考虑在内。通常的做法是在相关表的主键或高频查询字段上建立包含 tenantid 的复合索引。同时,应用程序在初始化数据库连接时,需要通过 SET LOCAL 指令将当前会话的租户上下文注入到数据库参数中,供 RLS 策略读取。
橙星云技术团队在评估这两种架构时,结合了自身业务中租户体量大但单租户数据量分布不均的特点。对于体量庞大且活跃度极高的头部租户,采用独立 Schema 甚至独立物理库进行隔离,以保证其资源独享和 SLA;而对于数量众多的中长尾租户,则使用 RLS 架构的共享存储池。这种混合模式能够在隔离性、运维复杂度与硬件成本之间取得合理的平衡。
在具体编码层面,引入 ORM 层的拦截器可以进一步降低开发者的心智负担。无论是动态切换 Schema 还是设置 RLS 上下文,都在中间件或数据库访问层收口。业务开发人员只需像操作单租户系统一样编写查询,底层自动完成租户路由。这样的工程设计有助于保持代码库的整洁,并降低因疏忽导致越权访问的风险。随着业务规模的演进,架构往往需要在隔离程度与资源利用率之间不断寻找新的平衡点。
