Muitas conexões com o banco de dados no Amazon RDS

9

Estamos tendo problemas com os usuários que executam consultas / visualizações no Drupal que ocasionalmente fazem com que nosso site congele. O congelamento ocorre porque a consulta faz com que o número de conexões com o banco de dados suba para mais de 400 e, basicamente, sempre que o site ultrapassar 100 conexões com o banco de dados, o site fica muito lento e simplesmente não responde.

Estamos executando o Amazon RDS usando o MySQL Red Hat Linux

Temos um EC2 grande o suficiente no servidor de aplicativos front-end e um RDS grande o suficiente.

A maneira como estamos corrigindo esse problema agora é encontrar a consulta incorreta e matá-la. Depois que a consulta é encerrada ... nossas conexões com o banco de dados caem para cerca de 20, que é a quantidade normal que você vê ao monitorar as estatísticas do site.

Existe uma maneira de parar a consulta incorreta e matá-la antes que ela demore muito e consuma as conexões? Eu estou tentando automatizar a eliminação da consulta incorreta antes que ela aconteça ou, pelo menos, após 30 segundos, é uma consulta incorreta e a mata.

ConcernedCEO
fonte
3
Matar a consulta por meio de um processo automatizado parece ser totalmente a abordagem errada ... se sua instância do RDS está realmente com pouca potência, causando o acúmulo inicial ... ou se há algo errado com a lógica do seu aplicativo, parece que está encontrando o problema real com a consulta seria a coisa a fazer ...
Michael - sqlbot
Você pode usar o MONyog-MySQL Monitor, que possui um sniffer baseado em PROCESSLIST, que ajuda a notificar e matar de consultas de longa duração. Também funciona bem com o Amazon RDS.
Peter Venderberghe
Não sendo um cara do MySql / Linux - como você pode ter mais de 100 conexões de um site? Eu faço apenas asp.net, e qualquer uma das minhas páginas abre apenas UMA conexão de cada vez - o que significa processar mais de 100 páginas ao mesmo tempo (na verdade, mais do que uma página só tem uma conexão aberta enquanto precisa). Eu examinaria sua abordagem de lidar com as conexões - isso é seriamente ineficiente.
TomTom
A AWS define o número máximo de conexões com base no tamanho da sua instância. a fórmula que eles usam é: max_connections = {DBInstanceClassMemory / 12582880} Consulte a documentação dos Grupos de parâmetros: https://console.aws.amazon.com/rds/home?region=us-east-1#parameter-groups:
Pode ser que você deva considerar a implementação de algum tipo de pool de conexão.
mustaccio

Respostas:

6

Aqui está um procedimento armazenado para eliminar SELECTs de execução longa

DELIMITER $$

DROP PROCEDURE IF EXISTS `test`.`Kill_Long_Running_Selects` $$
CREATE PROCEDURE `test`.`Kill_Long_Running_Selects` (time_limit INT,display INT)
BEGIN

    DECLARE ndx,lastndx INT;

    DROP TABLE IF EXISTS test.LongRunningSelects;
    CREATE TABLE test.LongRunningSelects
    (
        id INT NOT NULL AUTO_INCREMENT,
        idtokill BIGINT,
        PRIMARY KEY (id)
    ) ENGINE=MEMORY;
    INSERT INTO test.LongRunningSelects (idtokill)
    SELECT id FROM information_schema.processlist
    WHERE user<>'system user' AND info regexp '^SELECT' AND time > time_limit;

    SELECT COUNT(1) INTO lastndx FROM test.LongRunningSelects;
    SET ndx = 0;
    WHILE ndx < lastndx DO
        SET ndx = ndx + 1;
        SELECT idtokill INTO @kill_id
        FROM test.LongRunningSelects WHERE id = ndx;
        CALL mysql.rds_kill(@kill_id);
    END WHILE;

    IF lastndx > 0 THEN
        IF display = 1 THEN
            SELECT GROUP_CONCAT(idtokill) INTO @idlist FROM test.LongRunningSelects;
            SELECT @idlist IDs_KIlled;
            SELECT CONCAT('Processes Killed : ',lastndx) Kill_Long_Running_Selects;
        END IF;
    END IF;

END $$

Para eliminar SELECTs em execução por mais de 30 segundos, você executa este

CALL test.Kill_Long_Running_Selects(30,0);

Se você quiser ver as conexões sendo mortas, execute este

CALL test.Kill_Long_Running_Selects(30,1);

Talvez você possa criar um evento MySQL para chamar esse procedimento armazenado a cada minuto.

Se a Amazon não permitir que você tenha o privilégio EVENT , será necessário gravar um script de shell externo no servidor EC2 para conectar-se ao banco de dados e executar o Procedimento armazenado. Esse script de shell pode ser colocado em um crontab.

Se a Amazon não permitir que você tenha os privilégios PROCESS e SUPER , pode ser necessário mover o banco de dados para fora do RDS e para outra instância do EC2 executando o MySQL para fazer isso. Você pode criar o evento MySQL sem as restrições de hospedagem da Amazon.

RolandoMySQLDBA
fonte
11
Esta é uma ótima resposta! Eu usei no RDS hoje apenas mudando a linha KILL @kill_id; para "chamar mysql.rds_kill (@kill_id);" e funciona perfeitamente.
Dave R
@DaveR obrigado. Vou atualizar essa linha ainda hoje.
RolandoMySQLDBA
@DaveR Acabei de fazer essa alteração de linha. Obrigado por apontar isso.
RolandoMySQLDBA