Tôi đã có một ứng dụng web được xây dựng với Pyramid/SQLAlchemy/Postgresql và cho phép người dùng quản lý một số dữ liệu và dữ liệu đó gần như hoàn toàn độc lập với những người dùng khác nhau. Nói, Alice truy cập alice.domain.com
và có thể tải lên hình ảnh và tài liệu và Bob truy cập bob.domain.com
và cũng có thể tải lên hình ảnh và tài liệu. Alice không bao giờ thấy bất cứ điều gì được tạo bởi Bob và ngược lại (đây là một ví dụ đơn giản, có thể có rất nhiều dữ liệu trong nhiều bảng thực sự, nhưng ý tưởng là như nhau).Multi-tenancy với SQLAlchemy
Bây giờ, tùy chọn đơn giản nhất để tổ chức các dữ liệu trong backend DB là sử dụng một cơ sở dữ liệu duy nhất, nơi mỗi bảng (pictures
và documents
) có user_id
lĩnh vực, vì vậy, về cơ bản, để có được tất cả các hình ảnh của Alice, tôi có thể làm cái gì đó như
user_id = _figure_out_user_id_from_domain_name(request)
pictures = session.query(Picture).filter(Picture.user_id==user_id).all()
Đây là tất cả dễ dàng và đơn giản, tuy nhiên có một số nhược điểm
- tôi cần phải nhớ để luôn luôn sử dụng điều kiện lọc thêm khi thực hiện truy vấn, nếu không có thể thấy Alice pi của Bob ctures;
- Nếu có nhiều người sử dụng các bảng có thể phát triển lớn
- Nó có thể là khó khăn để phân chia các ứng dụng web giữa nhiều máy tính
Vì vậy, tôi nghĩ nó sẽ thực sự tốt đẹp để bằng cách nào đó chia dữ liệu mỗi -người dùng. Tôi có thể nghĩ đến hai phương pháp:
Có riêng bảng cho Alice và Bob hình ảnh và tài liệu trong cơ sở dữ liệu tương tự (Postgres' Schemas có vẻ là một cách tiếp cận đúng để sử dụng trong trường hợp này):
documents_alice documents_bob pictures_alice pictures_bob
và sau đó, sử dụng một số phép thuật bóng tối, "lộ trình" tất cả các truy vấn đến một hoặc vào bảng khác theo miền yêu cầu hiện tại của:
_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
Sử dụng một cơ sở dữ liệu riêng biệt cho mỗi người dùng:
- database_alice - pictures - documents - database_bob - pictures - documents
mà dường như là giải pháp sạch, nhưng tôi không chắc chắn nếu nhiều kết nối cơ sở dữ liệu sẽ đòi hỏi nhiều hơn nữa RAM và các nguồn lực khác, hạn chế số lượng càng tốt " người thuê nhà ".
Vì vậy, câu hỏi là, tất cả đều có ý nghĩa không? Nếu có, làm thế nào để cấu hình SQLAlchemy để sửa đổi tên bảng động trên mỗi yêu cầu HTTP (cho tùy chọn 1) hoặc để duy trì một nhóm kết nối tới cơ sở dữ liệu khác nhau và sử dụng kết nối đúng cho mỗi yêu cầu (cho tùy chọn 2)?
Liên quan chặt chẽ: http://stackoverflow.com/questions/9298296/ sqlalchemy-support-of-postgres-schemas –
@CraigRinger: vâng, nếu "SET search_path TO ..." thingie từ câu trả lời được chấp nhận hoạt động, đó sẽ là giải pháp cho tùy chọn # 1. Cảm ơn. – Sergey
Nếu bạn muốn tránh sharding cơ sở dữ liệu của bạn ngay lập tức dơi, có một cặp công thức nấu ăn trên sqlalchemy.org cho [Pre-Filtered Queries] (http://www.sqlalchemy.org/trac/wiki/UsageRecipes/PreFilteredQuery) và [Global Filters] (http://www.sqlalchemy.org/trac/wiki/UsageRecipes/GlobalFilter) có thể giúp bạn tránh việc kéo dữ liệu mà bạn không muốn vô tình. –