À l'extrémité inférieure, cela se résume essentiellement à "pouvez-vous absolument dire que vous n'avez pas de données partagées?" Contrairement à mysql, la base de données est une limite absolue dans postgresql. Vous ne pouvez pas SELECT zip_code FROM common.city_zip WHERE city=...
si vous allez avec des bases de données distinctes (du moins pas sans dblink
).
Si vous avez des données partagées, le "schéma" de postgresql est similaire à ce que mysql appelle une "base de données" . Tu peux CREATE SCHEMA clienta; CREATE TABLE clienta.customer (...);
. Vous créez un schéma pour chaque client, que l'utilisateur du client aurait leur schéma d' abord dans leur chemin de recherche, et les autorisations aurait été accordé afin que l'utilisateur du client A aurait accès aux clienta
et les public
schémas (et leurs tables).
Votre problème va être qu'à l'extrémité supérieure de # de clients, chaque table est stockée sous forme de fichier, donc si vous allez avec une base de données par client, un schéma par client, ou utilisez quelque chose comme ${client}_customer
pour vos noms de table, vous se heurtera probablement à des limites de filedescriptor avec des clients 10k même si vous n'aviez qu'une seule table par client (plus un filedescriptor par connexion). Bien sûr, vous pouvez ajuster le nombre maximal de descripteurs de fichiers du noyau à la volée à l'aide de sysctl, mais la limite par processus (ulimit) nécessitera de redémarrer postgresql si vous le définissez trop bas la première fois.
L'alternative est d'avoir "une grande table" avec une colonne client qui identifie le client auquel appartient cette ligne (idéalement, par nom d'utilisateur si vous avez un utilisateur par client, cela facilite les choses sous un LOT). En n'accordant aucun accès à cette table par les clients, vous pouvez créer des vues spécifiques au client (ou les utiliser session_user
pour identifier le client actuel). Cependant, les mises à jour ne peuvent pas être effectuées directement via une vue. Vous auriez besoin d'avoir des fonctions définies pour insérer / mettre à jour / supprimer sur la table (un ensemble de fonctions par client ou bien en utilisant session_user
) avec les fonctions utilisant SECURITY DEFINER
pour exécuter en tant qu'utilisateur spécial avec la permission d'insérer / mettre à jour / supprimer sur les tables (note : session_user
est utilisé parce que user
etcurrent_user
sont basés sur le contexte actuel, et dans une fonction DEFINIR DE SECURITE, ce serait toujours l'utilisateur qui a défini la fonction).
En termes de performances, au-delà du problème fd, je ne sais vraiment pas ce qui se passerait avec 10000 bases de données dans postgresql, par rapport à avoir une grande table avec 10000 données de clients. Une conception d'index appropriée doit empêcher la grande table d'être lente à interroger.
Je dirai que je suis allé avec des bases de données distinctes pour chaque client ici (nous ajoutons des serveurs pour garder le système utilisable, en déplaçant les bases de données client vers de nouveaux serveurs au besoin, nous n'atteindrons donc jamais 10 000 bases de données sur un seul serveur). J'ai dû restaurer les données des clients individuels à partir de sauvegardes pour le débogage ou en raison d'erreurs utilisateur sur une base régulière, quelque chose qui serait un cauchemar absolu sur la conception d'une "grande table". De plus, si vous avez l'intention de vendre la personnalisation de votre produit à vos clients, la conception d'une «grande table» pourrait vous empêcher de personnaliser le modèle de données.
pg_dump -n
(assurez-vous de vider votre schéma commun aussi!) Pour répertorier le schéma:psql -E
puis\dn
Sans plus de détails sur votre application, il est difficile de dire que vous obtiendrez une sécurité supplémentaire de cette configuration. Si chaque client se connecte à l'application Web et qu'il existe un utilisateur partagé de l'application Web à la base de données, vous n'avez pas isolé vos données d'une manière différente de l'utilisation d'une seule base de données monolithique. L'accès à vos données via des procédures stockées correctement paramétrées vous fournira le niveau d'isolement que vous recherchez sans le casse-tête administratif de gérer plus de 10 000 bases de données sur un nombre illimité de serveurs.
J'ai personnellement exécuté une configuration similaire sur un seul serveur de base de données en utilisant rien de plus que des procédures stockées paramétrées frappant une seule base de données. Si vous pouvez garantir que le seul accès à la base de données se fait par le biais de procédures stockées, il n'y a aucun risque de fusion des données dans les résultats.
Si vous voulez aller de l'avant avec votre conception, voici mes principales préoccupations:
ulimit -n
) sur votre système d'exploitation hôtela source
SELECT * WHERE clientId = 3
, vous avez une fuite de sécurité.