Ho un'applicazione Web che è stata creata con Pyramid/SQLAlchemy/Postgresql e consente agli utenti di gestire alcuni dati e che i dati sono quasi completamente indipendenti per i diversi utenti. Dire, Alice visita alice.domain.com
ed è in grado di caricare foto e documenti, e Bob visita bob.domain.com
ed è anche in grado di caricare foto e documenti. Alice non vede mai nulla creato da Bob e viceversa (questo è un esempio semplificato, potrebbero esserci molti dati in più tabelle, ma l'idea è la stessa).Multi-tenancy con SQLAlchemy
Ora, l'opzione più semplice per organizzare i dati nel backend DB è quello di utilizzare un unico database, dove ogni tavolo (pictures
e documents
) ha user_id
campo, quindi, in fondo, per ottenere tutte le immagini di Alice, posso fare qualcosa come
user_id = _figure_out_user_id_from_domain_name(request)
pictures = session.query(Picture).filter(Picture.user_id==user_id).all()
Questo è tutto facile e semplice, tuttavia ci sono alcuni svantaggi
- ho bisogno di ricordare di usare sempre condizione di filtro aggiuntivo quando si effettuano le query, altrimenti Alice può vedere pi di Bob ctures;
- Se ci sono molti utenti le tabelle possono crescere enorme
- Può essere difficile per dividere l'applicazione web tra più macchine
Così sto pensando che sarebbe davvero bello per dividere in qualche modo i dati per -utente. Mi vengono in mente due approcci:
Avere tavoli per Alice e Bob di immagini e documenti separati all'interno dello stesso database (Postgres' Schemas sembra essere un approccio corretto da utilizzare in questo caso):
documents_alice documents_bob pictures_alice pictures_bob
e poi, con un po 'di magia nera, "route" tutte le query per uno o per l'altra tabella in base al dominio del richiesta corrente:
_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
utilizzare un database separato per ogni utente:
- database_alice - pictures - documents - database_bob - pictures - documents
che sembra la soluzione più pulita, ma non sono sicuro se più connessioni al database richiederebbe molto più RAM e altre risorse, limitando il numero di possibili " inquilini".
Quindi, la domanda è: tutto ha senso? In caso affermativo, come posso configurare SQLAlchemy per modificare i nomi delle tabelle in modo dinamico su ogni richiesta HTTP (per l'opzione 1) o per mantenere un pool di connessioni a diversi database e utilizzare la connessione corretta per ogni richiesta (per l'opzione 2)?
Strettamente legato: http://stackoverflow.com/questions/9298296/ sqlalchemy-support-of-postgres-schemi –
@CraigRinger: sì, se il comando "SET search_path TO ..." dalla risposta accettata funziona, questa sarebbe una soluzione per l'opzione n. Grazie. – Sergey
Se vuoi evitare di condividere il tuo database subito, ci sono un paio di ricette su sqlalchemy.org per [Pre-Filtered Queries] (http://www.sqlalchemy.org/trac/wiki/UsageRecipes/PreFilteredQuery) e [Filtri globali] (http://www.sqlalchemy.org/trac/wiki/UsageRecipes/GlobalFilter) che possono aiutarti a evitare di estrarre dati che non vuoi per caso. –