我有一个使用Pyramid/SQLAlchemy/Postgresql构建的Web应用程序,它允许用户管理一些数据,而且这些数据几乎完全独立于不同的用户。说,爱丽丝访问alice.domain.com
,并能够上传图片和文件,鲍勃访问bob.domain.com
,也能够上传图片和文件。 Alice从来没有看到任何由Bob创建的东西,反之亦然(这是一个简化的例子,真的可能有很多数据在多个表中,但想法是相同的)。SQLAlchemy的多租户
现在,最直接的选择安排在数据库后端的数据是使用一个单一的数据库,其中每个表(pictures
和documents
)具有user_id
场,所以,基本上,让所有Alice的照片,我可以做像
user_id = _figure_out_user_id_from_domain_name(request)
pictures = session.query(Picture).filter(Picture.user_id==user_id).all()
这是所有容易和简单,但也有一些缺点
- 我需要记住进行查询时,总是使用额外的过滤条件,否则爱丽丝可能会看到Bob的PI ctures;
- 如果有许多用户表可能增长巨大
- 它可能很难拆分所以我想这将是非常好的每莫名其妙地分割数据多台机器
之间的Web应用程序-用户。我能想到的两种方法:
同一个数据库内单独表为Alice和Bob的图片和文档(Postgres的Schemas似乎是在这种情况下,使用正确的方法):
documents_alice documents_bob pictures_alice pictures_bob
,然后使用一些黑暗魔法,“路线”的所有查询到一个或根据当前请求的域中的其它表:
_use_dark_magic_to_configure_sqlalchemy('alice.domain.com') pictures = session.query(Picture).all() # selects all Alice's pictures from "pictures_alice" table ... _use_dark_magic_to_configure_sqlalchemy('bob.domain.com') pictures = session.query(Picture).all() # selects all Bob's pictures from "pictures_bob" table
使用单独的数据库为每个用户:
- database_alice - pictures - documents - database_bob - pictures - documents
这似乎是最干净的解决方案,但我不知道如果有多个数据库连接,将需要更多的内存和其他资源,限制可能的数字“租户”。
所以,问题是,这一切都有意义吗?如果是,我该如何配置SQLAlchemy以便在每个HTTP请求(对于选项1)上动态修改表名,或者维护到不同数据库的连接池并为每个请求使用正确的连接(对于选项2)?
密切相关:http://stackoverflow.com/questions/9298296/ sqlalchemy-support-postgres-schemas –
@CraigRinger:是的,如果从接受的答案中找到“SET search_path TO ...”thingie,那么这就是选项#1的解决方案。谢谢。 – Sergey
如果你想避免将数据库分割,那么sqlalchemy.org上有一对关于[Pre-Filtered Queries](预过滤查询)的食谱(http://www.sqlalchemy.org/trac/wiki/UsageRecipes/PreFilteredQuery)和[全局过滤器](http://www.sqlalchemy.org/trac/wiki/UsageRecipes/GlobalFilter),可以帮助您避免不必要地拉取不希望的数据。 –