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

9

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 car la requête fait monter le nombre de connexions à la base de données jusqu'à 400+ et, fondamentalement, chaque fois que le site dépasse 100 connexions à la 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 tombent à 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.

ConcernedCEO
la source
3
Tuer la requête via un processus automatisé semble être une approche totalement erronée ... que votre instance RDS soit en fait sous-alimentée, provoquant l'empilement initial ... ou qu'il y ait un problème avec la logique de votre application, il semble que vous trouviez le problème réel avec la requête serait la chose à faire ...
Michael - sqlbot
Vous pouvez utiliser MONyog-MySQL Monitor qui a un renifleur basé sur PROCESSLIST pour notifier et tuer les requêtes de longue durée. Cela fonctionne aussi bien avec Amazon RDS.
Peter Venderberghe
Ne pas être un gars MySql / Linux - comment pouvez-vous avoir plus de 100 connexions à partir d'un site Web? Je n'asp.net que, et n'importe laquelle de mes pages n'ouvre qu'une seule connexion à la fois - ce qui signifierait traiter plus de 100 pages en même temps (en fait, plus qu'une page n'a qu'une connexion ouverte tout en en ayant besoin). Je voudrais examiner votre approche de la gestion des connexions - qui est sérieusement inefficace.
TomTom
AWS définit le nombre maximal de connexions en fonction de la taille de votre instance. la formule qu'ils utilisent est: max_connections = {DBInstanceClassMemory / 12582880} Voir la documentation des groupes de paramètres: https://console.aws.amazon.com/rds/home?region=us-east-1#parameter-groups:
Vous devriez peut-être envisager d'implémenter une sorte de regroupement de connexions.
mustaccio

Réponses:

6

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 accorde pas le 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 la procédure stockée. 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 déplacer la base de données de RDS et vers 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.

RolandoMySQLDBA
la source
1
C'est une excellente réponse! Je l'ai utilisé sur RDS aujourd'hui en changeant simplement la ligne KILL @kill_id; pour "appeler mysql.rds_kill (@kill_id);" et cela fonctionne parfaitement.
Dave R
@DaveR merci. Je mettrai à jour cette ligne plus tard dans la journée.
RolandoMySQLDBA
@DaveR Je viens de faire ce changement de ligne. Merci de l'avoir signalé.
RolandoMySQLDBA