Answers:
在低端,它基本上可以归结为“您可以绝对地说您没有共享数据吗?” 与mysql不同,数据库是postgresql中的绝对约束。你不能SELECT zip_code FROM common.city_zip WHERE city=...
,如果你去与不同的数据库中(至少在没有dblink
)。
如果您有任何共享数据,则postgresql的“ schema”与mysql称为“ database”相似。你可以CREATE SCHEMA clienta; CREATE TABLE clienta.customer (...);
。您将为每个客户端创建一个架构,该客户端的用户将在其搜索路径中首先拥有其架构,并且将授予权限,以便客户端A的用户可以访问clienta
和和public
架构(及其表)。
您的问题将是,在#个客户端的高端,每个表都存储为一个文件,因此,无论您为每个客户端使用一个数据库,每个客户端使用一个架构还是${client}_customer
为表名使用诸如此类的名称,即使每个客户端只有一个表(每个连接加上一个filedescriptor),也可能遇到 10k客户端的filedescriptor限制。当然,您可以使用sysctl快速调整内核的最大文件描述符数量,但是如果您第一次设置的过低,则每个进程的限制(ulimit)将要求重新启动postgresql。
另一种方法是使用“一个大表”和一个客户列来标识该行属于哪个客户(理想情况下,如果每个客户只有一个用户,则按用户名,这会使很多东西变得更容易)。通过完全不授予客户端对该表的任何访问权限,您可以创建特定于客户端的视图(或用于session_user
标识当前客户端)。但是,无法直接通过视图进行更新。您将需要定义用于在表上插入/更新/删除的函数(每个客户端一组功能,或者使用session_user
),并具有SECURITY DEFINER
以特殊用户身份执行并具有在表上插入/更新/删除权限的函数(注意:session_user
用于因user
和current_user
是基于当前上下文,并且在SECURITY DEFINER函数中,该用户始终是定义该函数的用户)。
从性能角度来看,除了fd问题之外,老实说,我不知道在PostgreSQL中使用10000个数据库会发生什么,而在其中有一个包含10000个客户端数据的大表。正确的索引设计应防止大表被缓慢查询。
我会说我在这里为每个客户端使用了单独的数据库(我们添加服务器以保持系统的可用性,根据需要将客户端数据库转移到新服务器上,因此我们永远不会在一台服务器上使用1万个数据库)。我不得不从备份中恢复单个客户端的数据以进行调试或由于用户错误而定期恢复,这在“一个大表”设计上绝对是一场噩梦。同样,如果您打算将定制产品出售给客户,那么“一个大表”设计可能最终使您无法定制数据模型。
pg_dump -n
(一定也要转储您的通用架构!)列出架构来转储一个客户端架构:psql -E
然后\dn
如果没有有关您的应用程序的更多详细信息,很难说您将从此设置中获得任何额外的安全性。如果每个客户端都连接到Web应用程序,并且从Web应用程序到数据库都有一个共享用户,则您没有以与使用单个整体数据库不同的方式隔离数据。通过正确参数化的存储过程访问数据,将为您提供所需的隔离级别,而不会在任何数量的服务器上管理10,000多个数据库而带来管理上的麻烦。
我个人已经在单个数据库服务器上运行了类似的设置,所使用的只是参数化存储过程命中单个数据库。如果可以保证对数据库的唯一访问是通过存储过程,那么就不会有将数据混合到结果中的危险。
如果您确实想继续进行设计,这是我的主要担心:
ulimit -n
主机OS上打开的文件描述符()SELECT * WHERE clientId = 3
,则可能会导致安全漏洞。