No extremo inferior, basicamente se resume a "você pode dizer absolutamente que não possui dados compartilhados?" Diferente do mysql, o banco de dados é um limite absoluto no postgresql. Você não pode SELECT zip_code FROM common.city_zip WHERE city=...
se for com bancos de dados separados (pelo menos não sem dblink
).
Se você possui algum dado compartilhado, o "esquema" do postgresql é semelhante ao que o mysql chama de "banco de dados" . Você pode CREATE SCHEMA clienta; CREATE TABLE clienta.customer (...);
. Você poderia criar um esquema para cada cliente, o usuário do cliente teria seu esquema pela primeira vez em seu caminho de pesquisa, e seria concedido permissões para que o usuário do Cliente Um teriam acesso ao clienta
e os public
esquemas (e suas tabelas).
Seu problema será que, no final de # de clientes, cada tabela é armazenada como um arquivo. Portanto, se você usar um banco de dados por cliente, um esquema por cliente ou usar algo parecido ${client}_customer
com os nomes de suas tabelas, poderá é provável que atinja os limites do filedescriptor com 10 mil clientes, mesmo que você tenha apenas uma tabela por cliente (mais um filedescriptor por conexão). Obviamente, você pode ajustar o número máximo de descritores de arquivos do kernel em tempo real usando sysctl, mas o limite por processo (ulimit) exigirá a reinicialização do postgresql se você o definir muito baixo na primeira vez.
A alternativa é ter "uma grande tabela" com uma coluna de cliente que identifique a qual cliente essa linha pertence (idealmente, por nome de usuário, se você tiver um usuário por cliente, isso facilita muito as coisas abaixo). Ao não conceder nenhum acesso a essa tabela pelos clientes, você pode criar visualizações específicas do cliente (ou usar session_user
para identificar o cliente atual). As atualizações não podem ser feitas diretamente através de uma exibição. Você precisaria ter funções definidas para inserir / atualizar / excluir na tabela (um conjunto de funções por cliente ou usar session_user
) com as funções usadas SECURITY DEFINER
para executar como um usuário especial com permissão para inserir / atualizar / excluir nas tabelas (observação : session_user
é usado porque user
ecurrent_user
são baseados no contexto atual e, dentro de uma função DEFINER DE SEGURANÇA, esse sempre seria o usuário que definiu a função).
Em termos de desempenho, além da questão fd, sinceramente não sei o que aconteceria com 10000 bancos de dados no postgresql, em vez de ter uma tabela grande com 10000 dados de clientes. O design adequado do índice deve impedir que a tabela grande seja lenta para consulta.
Eu direi que optei por bancos de dados separados para cada cliente aqui (adicionamos servidores para manter o sistema utilizável, transferindo bancos de dados de clientes para novos servidores conforme necessário, para que nunca cheguemos a 10 mil bancos de dados em um servidor). Eu tive que restaurar os dados de clientes individuais de backups para depuração ou devido a erros do usuário regularmente, algo que seria um pesadelo absoluto no design de "uma grande mesa". Além disso, se você pretende vender a personalização do seu produto para seus clientes, o design de "uma grande mesa" pode acabar atrapalhando você na capacidade de personalizar o modelo de dados.
pg_dump -n
(certifique-se de despejar o esquema comum também!) Para listar o esquema:psql -E
então\dn
Sem mais detalhes sobre seu aplicativo, é difícil dizer que você obterá segurança adicional com essa configuração. Se cada cliente se conectar ao aplicativo Web e houver um usuário compartilhado do aplicativo Web no banco de dados, você não terá isolado seus dados de maneira diferente da utilização de um único banco de dados monolítico. O acesso aos seus dados por meio de procedimentos armazenados adequadamente parametrizados fornecerá o nível de isolamento que você procura, sem a dor de cabeça administrativa de gerenciar mais de 10.000 bancos de dados em qualquer número de servidores.
Pessoalmente, eu executei uma configuração semelhante em um único servidor de banco de dados usando nada além de procedimentos armazenados parametrizados, atingindo um único banco de dados. Se você pode garantir que o único acesso ao banco de dados é através de procedimentos armazenados, não há perigo de combinação de dados nos resultados.
Se você deseja avançar com seu design, aqui estão minhas principais preocupações:
ulimit -n
) no sistema operacional hostfonte
SELECT * WHERE clientId = 3
, você tem um vazamento de segurança.