Zu viele Datenbankverbindungen auf Amazon RDS

9

Wir haben Probleme mit Benutzern, die Abfragen / Ansichten in Drupal ausführen, die gelegentlich dazu führen, dass unsere Website einfriert. Das Einfrieren tritt auf, weil die Abfrage dazu führt, dass die Anzahl der Datenbankverbindungen auf über 400 steigt. Grundsätzlich verlangsamt sich die Site schrecklich, wenn die Site über 100 Datenbankverbindungen geht, und reagiert einfach nicht.

Wir führen Amazon RDS mit MySQL Red Hat Linux aus

Wir haben einen ausreichend großen EC2 auf dem Front-End-App-Server und einen ausreichend großen RDS.

Wir beheben dieses Problem jetzt, indem wir die fehlerhafte Abfrage finden und beenden. Sobald die Abfrage beendet ist ... fallen unsere Datenbankverbindungen auf etwa 20, was der normale Betrag ist, den Sie bei der Überwachung der Site-Statistiken sehen.

Gibt es eine Möglichkeit, die fehlerhafte Abfrage zu stoppen und zu beenden, bevor sie zu lange ausgeführt wird und die Verbindungen verbraucht? Ich versuche, das Beenden der fehlerhaften Abfrage zu automatisieren, bevor sie auftritt, oder zumindest nach 30 Sekunden zu erkennen, dass es sich um eine fehlerhafte Abfrage handelt, und sie zu beenden.

Betroffenes CEO
quelle
3
Das Beenden der Abfrage über einen automatisierten Prozess scheint völlig falsch zu sein. Unabhängig davon, ob Ihre RDS-Instanz tatsächlich nicht ausreichend ausgelastet ist und die anfängliche Anhäufung verursacht. Oder ob mit der Logik in Ihrer Anwendung etwas nicht stimmt, scheint es, als ob Sie das eigentliche Problem finden mit der Abfrage wäre die Sache zu tun ...
Michael - sqlbot
Sie können MONyog-MySQL Monitor mit PROCESSLIST-basiertem Sniffer verwenden, um lange laufende Abfragen zu benachrichtigen und zu töten. Es funktioniert auch gut mit Amazon RDS.
Peter Venderberghe
Sie sind kein MySQL / Linux-Typ - wie können Sie über 100 Verbindungen von einer Website aus herstellen? Ich mache nur asp.net und jede meiner Seiten öffnet jeweils nur EINE Verbindung - das würde bedeuten, dass mehr als 100 Seiten gleichzeitig verarbeitet werden (eigentlich mehr, da auf einer Seite nur eine Verbindung geöffnet ist, während sie benötigt wird). Ich würde Ihren Ansatz zum Umgang mit den Verbindungen untersuchen - das ist ernsthaft ineffizient.
TomTom
AWS legt die maximalen Verbindungen basierend auf der Größe Ihrer Instanz fest. Die verwendete Formel lautet: max_connections = {DBInstanceClassMemory / 12582880} Siehe Dokumentation zu Parametergruppen: https://console.aws.amazon.com/rds/home?region=us-east-1#parameter-groups:
Möglicherweise sollten Sie in Betracht ziehen, eine Art Verbindungspooling zu implementieren.
Mustaccio

Antworten:

6

Hier ist eine gespeicherte Prozedur zum Beenden von SELECTs mit langer Laufzeit

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

Um SELECTs zu beenden, die länger als 30 Sekunden laufen, führen Sie dies aus

CALL test.Kill_Long_Running_Selects(30,0);

Wenn Sie sehen möchten, dass die Verbindungen unterbrochen werden, führen Sie dies aus

CALL test.Kill_Long_Running_Selects(30,1);

Vielleicht können Sie ein MySQL-Ereignis erstellen, um diese gespeicherte Prozedur jede Minute aufzurufen.

Wenn Amazon Ihnen nicht die Berechtigung EVENT gewährt, müssen Sie ein externes Shell-Skript auf den EC2-Server schreiben, um eine Verbindung zur Datenbank herzustellen und die gespeicherte Prozedur auszuführen. Dieses Shell-Skript kann in eine Crontab eingefügt werden.

Wenn Amazon Ihnen nicht die Berechtigungen PROCESS und SUPER gewährt , müssen Sie möglicherweise die Datenbank aus RDS in eine andere EC2-Instanz verschieben, in der MySQL ausgeführt wird, um dies zu erreichen. Sie können das MySQL-Ereignis dann ohne die Hosting-Einschränkungen von Amazon erstellen.

RolandoMySQLDBA
quelle
1
Das ist eine großartige Antwort! Ich habe es heute auf RDS verwendet, indem ich nur die Zeile KILL @kill_id geändert habe. um "mysql.rds_kill (@kill_id) aufzurufen;" und es funktioniert perfekt.
Dave R
@ DaveR danke. Ich werde diese Zeile später heute aktualisieren.
RolandoMySQLDBA
@ DaveR Ich habe gerade diese Zeile geändert. Vielen Dank für den Hinweis.
RolandoMySQLDBA