Come funziona PostgreSQL con un gran numero di database?


9

Abbiamo un'applicazione Web la cui architettura richiede che qualsiasi utente registrato (un'azienda, in realtà) sia isolato dall'altro, ovvero eseguirò la stessa webapp con gli stessi modelli di dati, ma con set di dati diversi per ogni cliente.

Quindi, abbiamo pensato di creare un database diverso in Postgres per ogni cliente. Questa soluzione può adattarsi, per esempio, a database da 10-20K? Quanto bene?

Qualcuno ha una soluzione migliore per questo?

Grazie in anticipo.

Risposte:


10

Alla fine, si riduce sostanzialmente a "puoi assolutamente dire che non hai dati condivisi?" A differenza di mysql, il database è un punto di riferimento assoluto in postgresql. Non puoi SELECT zip_code FROM common.city_zip WHERE city=...se vai con database separati (almeno non senza dblink).

Se hai dei dati condivisi, lo "schema" di postgresql è simile a quello che mysql chiama "database" . Puoi CREATE SCHEMA clienta; CREATE TABLE clienta.customer (...);. Si potrebbe creare uno schema per ogni cliente, che l'utente del cliente avrebbe il loro schema prima nel loro percorso di ricerca, e le autorizzazioni sarebbe stato concesso in modo che l'utente del client A avrebbe accesso alla clientae publicschemi (e le loro tabelle).

Il tuo problema sarà che nella parte alta del numero di client, ogni tabella viene archiviata come file, quindi se vai con un database per client, uno schema per client o usi qualcosa di simile ${client}_customerper i nomi delle tue tabelle, probabilmente si imbatteranno in limiti di filedescriptor con client 10k anche se si avesse solo una tabella per client (più un filedescriptor per connessione). Naturalmente, è possibile regolare al volo il numero massimo di descrittori di file del kernel usando sysctl, ma il limite per processo (ulimit) richiederà il riavvio di postgresql se lo si imposta su un valore troppo basso la prima volta.

L'alternativa è avere "una grande tabella" con una colonna client che identifichi a quale client appartiene quella riga (idealmente, per nome utente se hai un utente per client, questo rende le cose sottostanti MOLTO più facili). Non garantendo alcun accesso a questa tabella da parte dei client, è possibile creare viste specifiche del client (o utilizzare session_userper identificare il client corrente). Tuttavia, gli aggiornamenti non possono essere eseguiti direttamente tramite una vista. Dovresti avere funzioni definite per inserire / aggiornare / eliminare sulla tabella (un set di funzioni per client o altro usando session_user) con le funzioni che usano SECURITY DEFINERper eseguire come utente speciale con il permesso di inserire / aggiornare / cancellare sulle tabelle (nota : session_userviene utilizzato perché userecurrent_user si basano sul contesto corrente e all'interno di una funzione DEFINER DI SICUREZZA sarebbe sempre l'utente che ha definito la funzione).

Dal punto di vista delle prestazioni, al di là del problema fd, onestamente non so cosa succederebbe con 10000 database in postgresql, rispetto a una tabella di grandi dimensioni con 10000 client di dati al suo interno. Una corretta progettazione dell'indice dovrebbe impedire che la tabella di grandi dimensioni sia lenta da interrogare.

Dirò che sono andato con database separati per ogni client qui (aggiungiamo server per mantenere il sistema utilizzabile, spostando i database client su nuovi server secondo necessità, quindi non arriveremo mai a 10k database su un server). Ho dovuto ripristinare i dati dei singoli clienti dai backup per il debug o a causa di errori dell'utente su base regolare, qualcosa che sarebbe stato un vero incubo sul design di "una grande tabella". Inoltre, se intendi vendere la personalizzazione del tuo prodotto ai tuoi clienti, il design di "un tavolo unico" potrebbe finire per ostacolarti per quanto riguarda la possibilità di personalizzare il modello di dati.


Ciao DerfK. Non riesco a usare l'approccio "un grande tavolo" a causa del motivo che hai dichiarato. Anche se oggi i modelli di dati sono gli stessi per tutti gli utenti, non possiamo garantire che saranno sempre gli stessi. Inoltre, non sapevo nulla del database assoluto in PSQL (dato che abbiamo alcuni dati condivisi). Penso di aver lasciato gli approcci di denominazione di tabelle e schemi. Nella tua esperienza, quanto è difficile gestire questo numero di database (anche in server diversi)?
Carlos,

@Eduardo La più grande difficoltà che ho con esso è assicurarsi che quando il modello di dati deve cambiare per tutti, sia fatto. Un giorno adatteremo qualcosa come il sistema di Rails per la gestione delle modifiche al modello di dati, fino ad allora ho uno script che scorre attraverso i client ed esegue lo stesso comando su ogni database. Dato che non condividiamo affatto dati condivisi, tutto il resto è stato abbastanza semplice. Se vai con un db con più schemi, puoi comunque scaricare uno schema client alla volta usando pg_dump -n(assicurati di scaricare anche lo schema comune!) Per elencare lo schema: psql -Equindi\dn
DerfK

@Eduardo non progetta per funzionalità che non hai ragione. Se così fosse la mia auto sarebbe un sottomarino e respingerebbe gli orsi e sarebbe in grado di volare sulla luna. Esistono molti solidi schemi di progettazione del database che ti permetteranno di iniziare con una tabella di grandi dimensioni e aggiungere funzionalità aggiuntive, se necessario. La chiave è chiederti di cosa hai bisogno oggi e cosa il tuo team operativo sarà in grado di supportare sulla base di proiezioni di crescita.
Jeremiah Peschka,

@DerfK, qual è lo stack web che usi oggi?
Carlos,

@Geremia, hai un buon punto. Hai esperienza con le applicazioni multi-tenant?
Carlos,

3

Senza ulteriori dettagli sulla tua applicazione, è difficile dire che otterrai questa sicurezza aggiuntiva da questa configurazione. Se ogni client si connette all'app Web e c'è un utente condiviso dall'app Web al database, allora non hai isolato i tuoi dati in modo diverso dall'uso di un singolo database monolitico. L'accesso ai tuoi dati tramite procedure memorizzate correttamente parametrizzate ti fornirà il livello di isolamento che stai cercando senza il mal di testa amministrativo della gestione di oltre 10.000 database su un numero qualsiasi di server.

Ho eseguito personalmente una configurazione simile su un singolo server di database utilizzando nient'altro che procedure memorizzate parametrizzate che colpiscono un singolo database. Se si può garantire che l'unico accesso al database sia attraverso le procedure memorizzate, non vi è pericolo che i dati si mescolino nei risultati.

Se vuoi andare avanti con il tuo design, ecco le mie preoccupazioni principali:

  1. a corto di descrittori di file aperti ( ulimit -n) sul sistema operativo host
  2. ottimizzazione di oltre 10.000 database per diversi modelli di query
  3. amministrare oltre 10.000 database con diversi problemi di sicurezza (backup e potenziali ripristini, vuoi davvero ripristinare oltre 10.000 database in caso di errore del server?)
  4. implementare le modifiche su oltre 10.000 database

E quanto sarebbe difficile eseguire il backup e ripristinare i dati di un client? È più facile farlo con procedure memorizzate o con schemi? Come hai affermato, il design dell'app utilizza solo un utente condiviso per connettersi al database. Inizialmente, l'approccio basato su più database è stato preso in considerazione per problemi di gestione piuttosto che per la sicurezza.
Carlos,

Le procedure memorizzate con parametri non proteggono da nient'altro che iniezioni di SQL. Se una di queste procedure fa un SELECT * WHERE clientId = 3, hai una perdita di sicurezza.
mikerobi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.