Marcelo Albuquerque
Posted on November 12, 2023
Uma breve análise da utilização do Pool de conexões do MySQL.
Considerações
- Next.js com a App Router
- Banco de dados MySQL utilizando Amazon RDS for MySQL
- Pacote MySQL2
Explicando o Problema
Trabalhando em uma aplicação comecei a receber uma mensagem de erro muito incomoda: Too many connections
, o código errno
é o 1040
.
Bem, obviamente havia algo errado. Antes de analisar o código da função para conexão ao bando de dados, observei que minha aplicação realizava muitas chamadas desnecessárias, então passei a guardar algumas informações em states
e trabalhei na otimização geral do código da aplicação.
Essa etapa foi muito importante, pois não podemos simplesmente sair disparando chamadas para o banco de dados de forma irresponsável.
Então enfim cheguei no código da função que realiza a conexão com o banco de dados e comecei a verificar - antes de realizar qualquer mudança - a quantidade conexões ao banco de dados toda vez que carregava a aplicação:
show status where `variable_name` = 'Threads_connected';
O que observei foi um número crescente de conexões, que invariavelmente poderia chegar ao limite do meu banco de dados na AWS, utilizo o Amazon RDS for MySQL.
Analisando a implementação atual
Agora observe o meu código de conexão ao banco de dados:
// libs/mysql/index.ts
import mysql from 'mysql2/promise';
/*
Com essa implementação, o número de conexões precisa ser muito controlado.
*/
export async function MySQL() {
const connection = await mysql.createConnection({
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USERNAME,
database: process.env.MYSQL_DATABASE,
password: process.env.MYSQL_PASSWORD
});
return connection
}
O detalhe principal é que estou utilizando o método createConnection
. E esta implementação precisa ser cuidadosamente estudada para ser implementada, pois toda chamada a ela irá gerar uma nova conexão ao banco de dados e claramente atingir o limite passa a ser apenas uma questão de tempo ou simplesmente de escalabilidade da aplicação.
Então comecei a ir atrás de soluções, estudar um pouco mais sobre implementações de conexão ao banco de dados MySQL.
Já havia ouvido sobre Pool de Conexões, mas nunca dei a devida atenção.
Aplicando a solução
Ótimo, conceitualmente é fantástico. A biblioteca que utilizo: MySQL 2 possuí este recurso, então bastava implementar e realizar os testes:
// /libs/mysql/index.ts
import mysql from 'mysql2'
export async function MySQL() {
const connection = mysql.createPool({
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USERNAME,
database: process.env.MYSQL_DATABASE,
password: process.env.MYSQL_PASSWORD
});
const pool = connection.promise()
return pool
}
Observe que agora estou utilizando o método createPool
.
Estou exportando uma função assíncrona, observe que a connection
gera uma promise
.
Vou deixar aqui apenas um exemplo de como utilizar esse Pool de conexões para gerar uma consulta no banco de dados:
// /api/consulta/route.ts
import { NextRequest, NextResponse } from 'next/server'
import MySQL from '/libs/mysql'
export async function GET( req: NextRequest ) {
try {
const mysql = await MySQL()
const query = `SELECT * FROM produtos`
const [ rows ] = await mysql.execute( query )
// Extremamente importante. Encerrar a conexão.
await mysql.end()
return NextResponse.json( rows )
} catch ( error ) {
return NextResponse.json( error )
}
}
Conclusão
Ao passar a utilizar o Pool de conexões observei que o número de conexões ao banco de dados diminuiu drasticamente, utilizando basicamente apenas uma única conexão.
Algo extremamente importante nessa implementação é o encerramento da conexão: await mysql.end()
principalmente utilizando funções assíncronas, caso contrário, o resultado seria o mesmo de utilizar o método createConnection
.
Infelizmente não dediquei o devido tempo ao estudo do MySQL, com certeza teria percebido esse problemas antes, mas deixo aqui para aqueles que de alguma forma possam estar enfrentando problemas semelhantes.
Comandos SQL que podem ser úteis
Exibir a quantidade de conexões ao banco de dados:
SHOW STATUS WHERE `variable_name` = 'Threads_connected';
Para analisar a proveniência das conexões:
SHOW processlist
Exibe o número máximo de conexões que seu banco de dados suporta:
SHOW VARIABLES LIKE "max_connections";
Referências
Também quero destacar uma postagem no Medium que me foi de grande ajudar, até considero que essa postagem deveria fazer parte da documentação oficial do MySQL 2. O autor se chamar Jorgen Lundgren.
Também obtive ajuda em uma pergunta no Stack Overflow onde nas respostas os usuários citaram diversos comandos úteis para o MySQL.
Posted on November 12, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.