Dissemos-lhes para não comprar mais RAM.
Uma loja online de artigos para o lar teve uma manhã de erros «too many connections». A solução óbvia era mais RAM. Os dados disseram para não a gastar: o working set já cabia em memória, e a resposta estava nas regras da própria aplicação.
Neste artigo 3 secções
- A base de dados de uma loja online de artigos para o lar começou a devolver ERROR 1040: Too many connections numa manhã, logo depois de o seu espaço de temp tables encher.
- A solução óbvia era mais RAM: uma base de dados maior do que o seu buffer pool parece faminta. Aumentar o pool teria custado dinheiro e não teria corrigido nada.
- A medição decidiu o contrário. O buffer pool acertava na cache quase sempre e ainda tinha espaço de sobra. O working set já estava em memória.
- A verdadeira causa era uma tabela de regras de desconto que tinha crescido muito para lá do que a loja precisava. A correção estava nas regras da aplicação, não em mais RAM.
Começou como uma manhã de erros de ligação. O espaço de temp tables, em tmpfs, tinha enchido, e segundos depois a base de dados começou a responder ERROR 1040: Too many connections. O nosso engenheiro de prevenção tinha-o no ecrã em poucos minutos, e trabalhámos nele em conjunto com os programadores da loja desde o início.
temp-table space (tmpfs) ........ FULL
… seconds later …
mysqld: ERROR 1040 (HY000): Too many connectionsA resposta cara, e porque a pusemos de lado
Uma base de dados maior do que o seu buffer pool, e memória livre na máquina. Todos os números à superfície apontam para o mesmo lado: dê mais RAM ao pool, está feito. Parece progresso e custa dinheiro a sério. A medição disse que não corrigiria nada.
| A RESPOSTA CARA | O QUE OS DADOS DISSERAM |
|---|---|
| A base de dados é maior do que o pool. Aumente o pool. | O rácio de cache-hit era quase perfeito. O working set já vivia em memória. |
| Uma cache maior corrige o transbordo. | O pool já tinha espaço por usar. Mais RAM poria em cache dados que já estavam em cache. |
| OS DADOS GANHARAMAcrescente hardware, problema resolvido. | A tabela sobredimensionada continua a crescer por trás do pool maior até transbordar outra vez. |
Duas leituras decidiram a questão. O buffer pool quase nunca falhava, e ainda tinha páginas livres. Juntas dizem uma coisa: o working set já cabia inteiramente em memória. Não havia dados à espera no disco para uma cache maior guardar.
A verdadeira causa estava nos tamanhos das tabelas
Com a memória fora de suspeita, fomos aos tamanhos das tabelas. Uma destacava-se: a tabela de combinações de regras de desconto, de longe o maior objeto da base de dados.
Essa tabela é gerada a partir das regras de desconto ativas da loja, e as combinações crescem com o quadrado do número de regras. Com o tempo as regras tinham-se acumulado, e a tabela tinha crescido com elas. As queries sobre ela estavam a transbordar o espaço de temp tables, e esse transbordo degenerava em esgotamento de ligações. O erro 1040 era o último dominó, não o primeiro.
# table name is an illustrative rename.
> table sizes, largest first
discount_rule_combinations largest table by a wide margin
↳ generated from the active discount rules
↳ combinations grow with the SQUARE of the rule countA resposta disciplinada e a resposta cara apontavam em sentidos opostos
Um pool maior teria comprado tempo, e a tabela teria continuado a crescer por trás dele. Só uma resposta tocava na causa real: arrumar as regras de desconto, limitar as combinações, e manter o hardware como estava. Os programadores da loja fizeram a alteração, e os erros pararam.
A máquina nunca foi o problema. Os dados mostraram que o working set já cabia em memória, por isso a correção estava nas regras da aplicação, não em mais RAM. A coisa mais útil que podíamos entregar a este cliente não era mais do nosso hardware. Era uma razão para não o comprar.
“Por vezes, a coisa mais valiosa que um fornecedor de hosting lhe pode dizer é: não gaste o dinheiro.”
Respostas diretas
A minha base de dados deu «ERROR 1040: Too many connections». Devo aumentar o limite de ligações?+
Normalmente não. Um teto mais alto não corrige o que quer que esteja a manter as ligações abertas, apenas deixa que se acumulem mais antes de algo disparar. Um limite sensato falha depressa e mantém os danos pequenos. Descubra o que está a prender as sessões antes de subir o número.
Devo acrescentar mais RAM se a minha base de dados for maior do que o meu buffer pool?+
Não com base nesse facto apenas. O número que decide é a taxa de acertos do buffer pool, não o tamanho em disco. Se o pool já acerta quase sempre e tem páginas livres, o working set cabe em memória e mais RAM poria em cache dados que já lá estão.
Qual é um rácio normal de acertos do buffer pool do InnoDB?+
Acima de 99 por cento assim que o working set cabe em memória. Se o pool já lá está e ainda tem páginas livres, um pool maior não compra nada. Olhe antes para as queries.
Porque é que o espaço de temp tables do meu MySQL está sempre a encher?+
Normalmente uma query que produz muito mais linhas intermédias do que o resultado precisa. Aqui, uma tabela de regras de desconto muito grande transbordou o espaço de temp tables, o que depois degenerou em esgotamento de ligações. A correção estava nos dados, não no disco.
A EuroVPS vai dizer-me para não comprar um upgrade?+
Sim, quando os dados dizem que o upgrade não corrige nada. Preferimos encontrar a causa real a vender-lhe hardware que a esconde. Neste caso a resposta honesta foi: não aumente o buffer pool, arrume as regras.
Antes de comprar o upgrade, deixe-nos ler os números.
Se uma máquina maior resolvesse o problema, dir-lhe-íamos. Se apenas escondesse a causa real, também o diremos, com a medição.
Fale com um engenheiroChegou ao fim.
Ponha a leitura em prática
O que executa?
Fale-nos da carga de trabalho, do tráfego e dos requisitos de recuperação. Comece pelo configurador de servidores ou discuta os detalhes com um engenheiro.
Escrito pelos engenheiros que constroem e operam a infraestrutura que descreve.Fale com um engenheiro
