Mandantenfähigkeit mit SQLAlchemy

8

Ich habe eine Web-Anwendung, die mit Pyramid / SQLAlchemy / Postgresql erstellt wurde und Benutzern erlaubt, einige Daten zu verwalten, und diese Daten sind für verschiedene Benutzer fast völlig unabhängig. Sagen wir, Alice besucht alice.domain.com und kann Bilder und Dokumente hochladen, und Bob besucht bob.domain.com und kann auch Bilder und Dokumente hochladen. Alice sieht nie etwas, das von Bob erstellt wurde, und umgekehrt (dies ist ein vereinfachtes Beispiel, es könnte wirklich eine Menge Daten in mehreren Tabellen geben, aber die Idee ist die gleiche) .

Die einfachste Möglichkeit, die Daten im DB-Backend zu organisieren, besteht nun darin, eine einzige Datenbank zu verwenden, in der jede Tabelle ( pictures und documents ) user_id field hat, also im Grunde alle Alice's Bilder, ich kann sowas wie

machen %Vor%

Das ist alles einfach und einfach, aber es gibt einige Nachteile

  • Ich muss daran denken, bei Anfragen immer eine Filterbedingung zu verwenden, sonst sieht Alice vielleicht Bobs Bilder;
  • Wenn es viele Benutzer gibt, können die Tabellen sehr groß werden
  • Es kann schwierig sein, die Webanwendung auf mehrere Rechner aufzuteilen

Also ich denke, es wäre wirklich nett, die Daten pro Benutzer irgendwie zu teilen. Ich kann mir zwei Ansätze vorstellen:

  1. Haben Sie separate Tabellen für Bilder und Dokumente von Alice und Bob innerhalb derselben Datenbank (Postgres ' Schemas scheint in diesem Fall ein richtiger Ansatz zu sein):

    %Vor%

    und dann, mit etwas dunkler Magie, "leiten" Sie alle Abfragen an die eine oder andere Tabelle entsprechend der Domäne der aktuellen Anfrage weiter:

    %Vor%
  2. Verwenden Sie für jeden Benutzer eine separate Datenbank:

    %Vor%

    scheint die sauberste Lösung zu sein, aber ich bin mir nicht sicher, ob mehrere Datenbankverbindungen viel mehr RAM und andere Ressourcen benötigen würden, was die Anzahl der möglichen "Mandanten" begrenzt.

Also, die Frage ist, macht das alles Sinn? Wenn ja, wie konfiguriere ich SQLAlchemy, um entweder die Tabellennamen dynamisch bei jeder HTTP-Anfrage (für Option 1) zu ändern oder um einen Pool von Verbindungen zu verschiedenen Datenbanken zu pflegen und die korrekte Verbindung für jede Anfrage zu verwenden (für Option 2)?

    
Sergey 14.11.2012, 02:02
quelle

3 Antworten

2

Ok, ich habe am Anfang jeder Anfrage% ce_de% geändert, indem ich Pyramid search_path -Ereignis benutzt habe:

%Vor%

Funktioniert wirklich gut, solange Sie die Transaktionsverwaltung an Pyramid übergeben (dh Transaktionen nicht manuell committen / zurückrollen, damit Pyramid dies am Ende der Anfrage tun kann) - was ok ist, wenn Sie Transaktionen manuell festschreiben Guter Ansatz sowieso.

    
Sergey 05.01.2013, 00:07
quelle
9

Nachdem ich über die Antwort von jd nachgedacht habe, konnte ich dasselbe Ergebnis für postgresql 9.2, sqlalchemy 0.8 und flask 0.9 framework erreichen:

%Vor%     
synergetic 12.09.2013 06:36
quelle
3

Was mir sehr gut gefällt, ist es, den Suchpfad auf der Verbindungspoolebene anstatt in der Sitzung festzulegen. In diesem Beispiel wird Flask und seine Thread-lokalen Proxies verwendet, um den Schemanamen zu übergeben, sodass Sie schema = current_schema._get_current_object() und den try-Block um ihn herum ändern müssen.

%Vor%

Zum Zeitpunkt der Motorerstellung:

%Vor%     
jd. 15.12.2012 09:39
quelle