Wie gut funktioniert PostgreSQL mit einer großen Anzahl von Datenbanken?

9

Wir haben eine Webanwendung, deren Architektur erfordert, dass jeder registrierte Benutzer (eigentlich ein Unternehmen) vom anderen isoliert ist, dh ich verwende dieselbe Webanwendung mit denselben Datenmodellen, aber mit unterschiedlichen Datensätzen für jeden Kunden.

Daher haben wir darüber nachgedacht, für jeden Kunden eine andere Datenbank in Postgres zu erstellen. Kann diese Lösung beispielsweise auf 10 bis 20 KB Datenbanken skaliert werden? Wie gut?

Hat jemand eine bessere Lösung dafür?

Danke im Voraus.

Carlos
quelle

Antworten:

9

Am unteren Ende läuft es im Grunde auf "Können Sie absolut sagen, dass Sie keine gemeinsamen Daten haben?" Im Gegensatz zu MySQL ist die Datenbank in PostgresQL eine absolute Grenze. Sie können nicht, SELECT zip_code FROM common.city_zip WHERE city=...wenn Sie mit separaten Datenbanken gehen (zumindest nicht ohne dblink).

Wenn Sie überhaupt gemeinsam genutzte Daten haben, ähnelt das "Schema" von postgresql dem, was mysql als "Datenbank" bezeichnet . Du kannst CREATE SCHEMA clienta; CREATE TABLE clienta.customer (...);. Sie würden ein Schema für jeden Client erstellen, der Benutzer des Clients würde sein Schema zuerst in seinem Suchpfad haben, und Berechtigungen würden erteilt, damit der Benutzer von Client A Zugriff auf das clientaund die publicSchemas (und ihre Tabellen) hat.

Ihr Problem wird sein, dass am oberen Ende der Anzahl der Clients jede Tabelle als Datei gespeichert wird. Unabhängig davon, ob Sie eine Datenbank pro Client, ein Schema pro Client verwenden oder etwas Ähnliches ${client}_customerfür Ihre Tabellennamen verwenden, werden Sie dies tun Wahrscheinlich stoßen Sie bei 10.000 Clients auf Limits für Dateiskriptoren, selbst wenn Sie nur eine Tabelle pro Client hatten (plus einen Dateiskriptor pro Verbindung). Natürlich können Sie die maximale Anzahl von Dateideskriptoren des Kernels im laufenden Betrieb mit sysctl anpassen, aber das Pro-Prozess-Limit (ulimit) erfordert einen Neustart von postgresql, wenn Sie es beim ersten Mal zu niedrig einstellen.

Die Alternative besteht darin, "eine große Tabelle" mit einer Client-Spalte zu haben, die angibt, zu welchem ​​Client diese Zeile gehört (idealerweise nach Benutzername, wenn Sie einen Benutzer pro Client haben, erleichtert dies die Dinge unter einer Menge). Indem Sie den Clients überhaupt keinen Zugriff auf diese Tabelle gewähren, können Sie clientspezifische Ansichten erstellen (oder session_userzur Identifizierung des aktuellen Clients verwenden). Aktualisierungen können jedoch nicht direkt über eine Ansicht durchgeführt werden. Sie müssten definierte Funktionen zum Einfügen / Aktualisieren / Löschen in die Tabelle haben (ein Satz von Funktionen pro Client oder Verwendung session_user), wobei die Funktionen verwendet werden SECURITY DEFINER, um als spezieller Benutzer mit der Berechtigung zum Einfügen / Aktualisieren / Löschen in die Tabellen ausgeführt zu werden (Hinweis : session_userwird verwendet, weil userundcurrent_user basieren auf dem aktuellen Kontext und innerhalb einer SECURITY DEFINER-Funktion ist dies immer der Benutzer, der die Funktion definiert hat.

In Bezug auf die Leistung weiß ich ehrlich gesagt nicht, was mit 10000 Datenbanken in postgresql passieren würde, im Gegensatz zu einer großen Tabelle mit Daten von 10000 Clients. Ein korrektes Indexdesign sollte verhindern, dass die große Tabelle langsam abgefragt wird.

Ich werde sagen, dass ich hier für jeden Client separate Datenbanken verwendet habe (wir fügen Server hinzu, um das System nutzbar zu halten, und verschieben Client-Datenbanken nach Bedarf auf neue Server, sodass wir niemals auf 10.000 Datenbanken auf einem Server zugreifen können). Ich musste die Daten einzelner Clients aus Backups zum Debuggen oder aufgrund von Benutzerfehlern regelmäßig wiederherstellen, was ein absoluter Albtraum für das Design "one big table" wäre. Wenn Sie beabsichtigen, die Anpassung Ihres Produkts an Ihre Kunden zu verkaufen, kann das Design "one big table" Sie möglicherweise daran hindern, das Datenmodell anzupassen.

DerfK
quelle
Hallo DerfK. Ich kann den "One Big Table" -Ansatz aus dem von Ihnen angegebenen Grund nicht verwenden. Auch wenn die Datenmodelle heute für jeden Benutzer gleich sind, können wir nicht garantieren, dass sie immer gleich sind. Außerdem wusste ich nichts über die absolute Datenbankgrenze in PSQL (da wir einige gemeinsam genutzte Daten haben). Ich glaube, ich habe die Ansätze für Schema- und Tabellennamen verlassen. Wie schwierig ist es Ihrer Erfahrung nach, diese Anzahl von Datenbanken zu verwalten (auch auf verschiedenen Servern)?
Carlos
@Eduardo Die größte Schwierigkeit, die ich damit habe, besteht darin, sicherzustellen, dass das Datenmodell, wenn es für alle geändert werden muss, erledigt wird. Eines Tages werden wir so etwas wie das System von Rails anpassen, um Änderungen am Datenmodell zu verwalten. Bis dahin habe ich ein Skript, das die Clients durchläuft und auf jeder Datenbank den gleichen Befehl ausführt. Da wir überhaupt keine gemeinsam genutzten Daten erstellen, war alles andere ziemlich einfach. Wenn Sie mit einer Datenbank mit mehreren Schemas arbeiten, können Sie immer noch ein Client-Schema gleichzeitig pg_dump -npsql -E\dn
sichern,
@Eduardo entwirft nicht für Funktionen, die Sie nicht richtig haben. Wenn das der Fall wäre, wäre mein Auto ein U-Boot und würde Bären abwehren und könnte zum Mond fliegen. Es gibt viele solide Datenbankentwurfsmuster, mit denen Sie mit einer großen Tabelle beginnen und bei Bedarf zusätzliche Funktionen hinzufügen können. Der Schlüssel ist, sich zu fragen, was Sie heute brauchen und was Ihr Ops-Team basierend auf Wachstumsprognosen unterstützen kann.
Jeremiah Peschka
@DerfK, welchen Webstack verwenden Sie heute?
Carlos
@ Jeremiah, du hast einen guten Punkt. Haben Sie Erfahrung mit Anwendungen mit mehreren Mandanten?
Carlos
3

Ohne weitere Details zu Ihrer Anwendung ist es schwierig zu sagen, dass Sie durch diese Einrichtung zusätzliche Sicherheit erhalten. Wenn jeder Client eine Verbindung zur Web-App herstellt und sich ein freigegebener Benutzer von der Web-App zur Datenbank befindet, haben Sie Ihre Daten nicht auf eine Weise isoliert, die sich von der Verwendung einer einzelnen monolithischen Datenbank unterscheidet. Durch den Zugriff auf Ihre Daten über ordnungsgemäß parametrisierte gespeicherte Prozeduren erhalten Sie die Isolationsstufe, die Sie suchen, ohne die administrativen Probleme bei der Verwaltung von mehr als 10.000 Datenbanken auf einer beliebigen Anzahl von Servern.

Ich persönlich habe eine ähnliche Einrichtung auf einem einzelnen Datenbankserver ausgeführt, wobei nur parametrisierte gespeicherte Prozeduren verwendet wurden, die auf eine einzelne Datenbank treffen. Wenn Sie sicherstellen können, dass der einzige Zugriff auf die Datenbank über gespeicherte Prozeduren erfolgt, besteht keine Gefahr, dass sich Daten in den Ergebnissen vermischen.

Wenn Sie mit Ihrem Design fortfahren möchten, sind hier meine Hauptanliegen:

  1. ulimit -nAuf Ihrem Host-Betriebssystem gehen die offenen Dateideskriptoren ( ) aus
  2. Optimieren von mehr als 10.000 Datenbanken für verschiedene Abfragemuster
  3. Verwalten von mehr als 10.000 Datenbanken mit unterschiedlichen Sicherheitsbedenken (Backups und potenzielle Wiederherstellungen. Möchten Sie wirklich mehr als 10.000 Datenbanken wiederherstellen, wenn ein Serverfehler auftritt?)
  4. Einführung von Änderungen in mehr als 10.000 Datenbanken
Jeremiah Peschka
quelle
Und wie schwierig wäre es, die Daten eines Kunden zu sichern und wiederherzustellen? Ist dies mit gespeicherten Prozeduren oder mit Schemas einfacher? Wie Sie bereits angegeben haben, verwendet das App-Design nur einen freigegebenen Benutzer, um eine Verbindung zur Datenbank herzustellen. Zunächst wurde der Ansatz mit mehreren Datenbanken eher aus Managementgründen als aus Sicherheitsgründen in Betracht gezogen.
Carlos
Parametrisierte gespeicherte Prozeduren schützen nur vor SQL-Injektionen. Wenn eines dieser Verfahren a SELECT * WHERE clientId = 3ausführt, liegt ein Sicherheitsleck vor.
Mikerobi