Lembro-me dos podcasts do stackoverflow que o Fog Creek usa um banco de dados por cliente para o Fogbugz . Presumo que isso signifique que os servidores Fogbugz On Demand tenham dezenas de milhares de bancos de dados.
Estamos apenas começando a desenvolver um aplicativo web e temos um problema semelhante para resolver (muitos clientes com seus próprios dados isolados).
Que problemas devo esperar ao usar um banco de dados por cliente? Como posso resolvê-los?
Meus pensamentos iniciais
Vantagens de um banco de dados por cliente
- Esquema de banco de dados mais simples
- Backups mais simples - você pode fazer backup de cada cliente sem que isso realmente afete outros clientes.
- Facilita a exportação de dados de determinados clientes.
- Melhor desempenho de cache - uma gravação em uma das tabelas mais ativas afeta apenas aquele único cliente que executou a gravação.
- Mais fácil de dimensionar em hardware. Por exemplo, quando precisamos passar de 1 para 2 servidores, apenas movemos metade de nossos clientes para o novo servidor.
Desvantagens
- O MySQL pode lidar com 5.000 bancos de dados? O desempenho seria péssimo?
- As alterações no esquema podem ser difíceis de replicar em todos os bancos de dados. Realmente teríamos que ter um plano automatizado para isso, como versionar o esquema e um script que entendesse como levar um banco de dados de uma versão para outra.
- Fazer qualquer coisa que seja comum a todos os nossos clientes pode ser estranho ou impossível
- Semelhante ao acima, mas qualquer análise que desejemos realizar em todos os nossos clientes pode ser impossível. Como devemos rastrear o uso em todos os clientes, por exemplo?
Essa solução é chamada de design multilocatário, onde cada locatário (cliente) possui seu próprio banco de dados. Dado isso, existem algumas outras considerações para a abordagem alternativa que é um único banco de dados:
Ter bancos de dados separados significa que você precisa criar um mecanismo de atualização que corresponda à versão do banco de dados com a versão do aplicativo/site. No entanto, bancos de dados separados fornecem isolamento superior de dados e o IMO tem um custo menor de hospedagem. Não é uma solução para todos os cenários. Se o seu sistema nunca fosse hospedado fora de sua hospedagem e precisasse aumentar rapidamente os clientes e ter todos os usuários na mesma versão do aplicativo e do esquema de banco de dados era desejável, certamente ter um único banco de dados é uma abordagem melhor.
Na minha experiência, você não deve criar um banco de dados por cliente. Deixe-me lhe dar um exemplo:
No ano passado trabalhei com 70 bancos de dados (muito menos de 5000), cada um com o mesmo esquema e tudo. Em teoria, as coisas correriam como planejado (como você mencionou na seção de vantagens), mas na realidade nem tanto. Tivemos muitos problemas com a atualização de esquemas, suporte ao usuário, atualização de software, o que você quiser. Foi terrível.
Usamos Firebird e fui contratado logo após o lançamento do produto, mas isso me deu o conhecimento para nunca trabalhar com bancos de dados separados.
Não estou dizendo que você não pode fazer isso, estou dizendo que as coisas podem dar muito errado e, para ser honesto, sua lista de vantagens não parecia atraente o suficiente para correr o risco. A maioria deles pode ser realizada com um único banco de dados.
Você provavelmente gostaria de manter outro banco de dados para rastrear a versão em que cada cliente está, para poder acompanhar quais deles passaram ou não passaram pela última rodada de modificações.
Fazer o script das atualizações não seria tão difícil... você poderia escrever algo que olhasse para o catálogo de bancos de dados e aplicasse as alterações necessárias para obter cada banco de dados para a versão mais recente, possivelmente ignorando aqueles que não deveriam ser atualizados por algum motivo.
Como os 'bancos de dados' do mysql são apenas esquemas, como Caio apontou, se tudo estiver sendo executado na mesma instância do servidor, você pode apenas qualificar o nome das tabelas que está tentando modificar ou obter informações:
...
Se você começar a dividir as coisas em vários servidores, ainda poderá criar um script que faça conexões com vários servidores para que possa aplicar todas as alterações; para a análise, novamente, você pode definir vários links de banco de dados usando tabelas federadas em seu banco de dados mestre para acessar os dados de um lugar, pois você estaria lendo as tabelas.
...
Além disso, esteja ciente de que eles não estão usando o mySQL para troca de pilha, eles estão usando o SQL Server.
E não tenho ideia de que tipo de sobrecarga de desempenho haveria no mysql nessa escala, acho que nunca passei de 30 'bancos de dados' no mysql.
Eu tenho um cliente Web/DB Hosting que tem mais de 750 bancos de dados de clientes com o mesmo número de tabelas (162) e as mesmas estruturas de tabela. Combinados, todos os dados do cliente do meu cliente totalizam 524 GB (95% InnoDB)
Imagine todos esses bancos de dados competindo por 13 G de buffer pool innodb em nove servidores de banco de dados por meio de replicação circular. Escalar com essa configuração de hardware não foi suficiente. Imediatamente, recomendamos ao cliente que escalasse.
Recentemente, migramos este cliente para servidores de 3 BD com muito mais potência (a todo custo, fique longe de SSD em ambientes de alta gravação, SEMPRE !!!). Nós os atualizamos do MySQL 5.0.90 para o MySQL 5.5.9. Diferenças dramáticas foram vistas quase instantaneamente.
O dimensionamento horizontal também deve ser considerado porque, se você tiver centenas de clientes atingindo os mesmos recursos de memória e disco, o dimensionamento reduz seu uso linearmente (O(n)), em que n é baseado no número de servidores de banco de dados em um ambiente multimestre.
No caso do meu cliente, minha empresa está reduzindo ele de 9 servidores DB (Quad Code, 32GB RAM, 824G RAID10) para servidores DB mais rápidos (Dual HexaCore [isso mesmo 12 CPUs], 192GB RAM,1.7TB RAID10) do MySQL 5.5 .9 (para tabela aproveitar as múltiplas CPUs). Além disso, imagine um pool de buffer innodb de 150 GB em 50 partições de 3 GB cada (vários pools de buffer InnoDB são um novo recurso no MySQL 5.5). Uma expansão menor, mas uma expansão massiva, funcionou para a infraestrutura exclusiva do meu cliente.
MORAL DA HISTÓRIA : Aumentar ou diminuir a escala nem sempre é a solução se você tiver tabelas mal projetadas. O que quero dizer é o seguinte: se as páginas de índice têm população de chaves desequilibrada para índices de várias colunas, consultar chaves das partes desiguais dos índices leva à varredura de tabela após varredura de tabela, ou pelo menos índices que nunca são usados devido a serem descartados pela consulta do MySQL Otimizador. Simplesmente não há substituto para o design adequado.
O MySQL cria bancos de dados em diretórios separados, então depende muito do sistema operacional subjacente e de quantas pastas / manipuladores de arquivos ele pode manipular. Não deve ser um problema com os sistemas operacionais modernos, mas é daí que vem grande parte do gargalo.
Não há nada dizendo que você precisa hospedar versões diferentes do banco de dados ou do aplicativo. O que há de errado em simplesmente isolar os dados fazendo um db por cliente e tendo uma versão do banco de dados e do aplicativo? É claro que cada banco de dados do cliente teria que ser clonado a partir de um modelo da versão de trabalho atual. Do ponto de vista de segurança e isolamento de dados, acho que isso é o ideal.
A única desvantagem que posso ver é que você teria que atualizar manualmente cada banco de dados ao criar uma nova versão. Isso poderia ser facilmente automatizado embora.