首页 > 解决方案 > 如何为多租户 Web 应用程序动态创建模式/表

问题描述

问题

我正在构建一个网络应用程序,每个用户都需要隔离数据(由于机密性),但具有完全相同的数据结构/表。

环顾四周我觉得这个概念叫多租户?似乎一个好的解决方案是每个租户 1 个模式。

我认为sqlalchemy 1.1对此实现了一些支持

session.connection(execution_options={
    "schema_translate_map": {"per_user": "account_one"}})

然而,这似乎假设架构和表已经创建。

我不确定我将拥有多少租户,所以我需要在创建用户帐户时动态创建架构和其中的表。

解决方案

我想出的东西感觉有点像黑客,这就是为什么我在这里发帖看看是否有更好的解决方案。

为了即时创建模式,我正在使用

if not engine.dialect.has_schema(engine, user.name):
   engine.execute(sqlalchemy.schema.CreateSchema(user.name))

然后直接在之后我使用创建表

table = TableModel()
table.__table__.schema = user.name
table.__table__.create(db.session.bind)

将 TableModel 定义为

class TableModel(Base):

    __tablename__ = 'users'

    __table_args__ = {'schema': 'public'}

    id = db.Column(
        db.Integer,
        primary_key=True
    )

    ...

我不太清楚为什么要从 Base vs db.Model 继承 - db.Model 似乎会自动公开创建表,我想避免这种情况。

奖金问题

创建架构后,如果我需要将表添加到所有架构中 - 管理它的最佳方法是什么?烧瓶迁移本身可以处理吗?

谢谢!

标签: postgresqlflasksqlalchemyflask-sqlalchemymulti-tenant

解决方案


如果将来有人看到这一点,则此解决方案似乎可以广泛使用,但是我最近遇到了一个问题。

这条线

table.__table__.schema = user.name

似乎会产生一些奇怪的行为,其中 user.name 的值似乎在应用程序的顺序区域中持续存在,因此如果您切换用户,则会错误地查询前一个用户的表。

我不完全确定为什么会发生这种情况,并且仍在研究如何解决它。


推荐阅读