若尔营建多租户之SaaS,此乃架构之始也。
若误,此决将萦绕君心。
吾已将二法皆付诸实践。此诚为坦荡之权衡。
A:共享模式,具行级安全(RLS)
每租户之数据,皆存于同表。每表有租户ID列焉。
行。PostgreSQL RLS之策,强制查询所返之列,唯属今租者。
-- Enable RLS on the table
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
-- Policy: users only see their tenant's rows
CREATE POLICY tenant_isolation ON orders
USING (tenant_id = current_setting('app.current_tenant_id')::uuid);
# Set the tenant context before every query
async def set_tenant(conn, tenant_id: str):
await conn.execute(
"SELECT set_config('app.current_tenant_id', $1, true)",
tenant_id
)
效佳之时:汝有众多小租者。百或千。
户分架构于斯,难于驾驭——迁更独需时辰之巨。
弊生之时:喧嚣之户发重询,致他户之效损。难易移一户之数据于别库。需异户存异策。
择二:户分架构
每户得自具之PostgreSQL架构——实为名域。
租户abc之订单,租户xyz之订单。同表异构也。
-- Create schema for a new tenant
CREATE SCHEMA tenant_abc;
-- Set search path at connection time
SET search_path TO tenant_abc, public;
# Alembic migration across all tenant schemas
from alembic import command
from alembic.config import Config
def migrate_all_tenants(tenant_schemas: list[str]):
for schema in tenant_schemas:
alembic_cfg = Config("alembic.ini")
alembic_cfg.set_main_option("sqlalchemy.url", db_url)
alembic_cfg.set_section_option("alembic", "version_table_schema", schema)
command.upgrade(alembic_cfg, "head")
当租户较少而规模较大时,企业客户使用效果甚佳。
何人需数据隔离之保证,定制留存,或能
其全数据集,洁然导出之。
中断之时:汝有五百租户以上。行迁移于五百
依序处理模式,则迟滞。连接池之负担渐增。
吾所实用者
于初兴之SaaS产品,多从RLS始。此法简明易行。
運作無難,遷移輕易,汝恆可移至每租戶一模式
为日后特定巨擘,导之至专属架构
,乃至专属数据库
。此混合之策——于中小企业租户施用行级权限控制,于企业建专属架构——
,乃吾所定。尔之连接链,即为此路由器
def get_db_url(tenant: Tenant) -> str:
if tenant.tier == "enterprise":
return tenant.dedicated_db_url
return f"{shared_db_url}?options=-csearch_path={tenant.schema}"
一物无人告汝:试汝RLS之策,当禁超级用户。
PostgreSQL超用户默认可绕过RLS。汝之试运行环境运行
为超用户者,永难察失政之策。试时当用限权之职。












