web-dev-qa-db-fra.com

Trop de connexions à la base de données sur Amazon RDS

Nous rencontrons des problèmes avec les utilisateurs exécutant des requêtes/vues dans Drupal qui provoquent parfois le gel de notre site. Le gel se produit parce que la requête fait monter le nombre de connexions à la base de données jusqu'à 400+ et essentiellement à tout moment le site dépasse les 100 connexions de base de données, le site ralentit terriblement et ne répond tout simplement pas.

Nous exécutons Amazon RDS à l'aide de MySQL Red Hat Linux

Nous avons un EC2 assez grand sur le serveur d'applications frontal et un RDS assez grand.

La façon dont nous résolvons ce problème maintenant est de trouver la requête incriminée et de la tuer. Une fois la requête supprimée ... nos connexions à la base de données chutent à environ 20, ce qui est le montant normal que vous voyez lors de la surveillance des statistiques du site.

Existe-t-il un moyen d'arrêter la requête incriminée et de la tuer avant qu'elle ne s'exécute trop longtemps et consomme les connexions? J'essaie d'automatiser la suppression de la mauvaise requête avant qu'elle ne se produise, ou du moins de réaliser après 30 secondes que c'est une mauvaise requête et de la tuer.

9
ConcernedCEO

Voici une procédure stockée pour tuer les SELECT de longue durée

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 $$

Pour tuer les SELECT qui durent plus de 30 secondes, vous exécutez ceci

CALL test.Kill_Long_Running_Selects(30,0);

Si vous voulez voir les connexions tuées, vous exécutez cette

CALL test.Kill_Long_Running_Selects(30,1);

Vous pouvez peut-être créer un événement MySQL pour appeler cette procédure stockée toutes les minutes.

Si Amazon ne vous laisse pas disposer du privilège EVENT , vous devrez écrire un script Shell externe sur le serveur EC2 pour vous connecter à la base de données et exécuter le Stored. Procédure. Ce script Shell peut être placé dans une crontab.

Si Amazon ne vous laisse pas disposer des privilèges PROCESS et SUPER , vous devrez peut-être pour déplacer la base de données hors de RDS et dans une autre instance EC2 exécutant MySQL pour y parvenir. Vous pouvez ensuite créer l'événement MySQL sans les restrictions d'hébergement d'Amazon.

6
RolandoMySQLDBA