Amazon RDS上的数据库连接过多


9

用户在Drupal中运行查询/视图时遇到问题,有时会导致我们的网站冻结。发生冻结是因为查询导致数据库连接数增加到400个以上,并且基本上在站点超过100个数据库连接的任何时候,站点都会严重减速,并且没有响应。

我们正在使用MySQL Red Hat Linux运行Amazon RDS

我们的前端应用服务器上有足够大的EC2,还有足够大的RDS。

我们现在解决此问题的方法是找到有问题的查询,然后将其杀死。一旦查询被终止,我们的数据库连接将下降到20左右,这是监视站点统计信息时看到的正常数量。

有没有办法停止令人讨厌的查询并在它运行太长时间并消耗连接之前将其杀死?我试图在错误查询发生之前自动将其杀死,或者至少在30秒后意识到错误查询并将其杀死。


3
通过自动化过程终止查询似乎是完全错误的方法……无论您的RDS实例实际上是否功能不足,导致初始堆积……还是您的应用程序中的逻辑有问题,似乎都在寻找实际问题与查询将是要做的事...
Michael-sqlbot

您可以使用具有基于PROCESSLIST的嗅探器的MONyog- MySQL Monitor来通知和杀死长时间运行的查询。它也适用于Amazon RDS。
Peter Venderberghe 2013年

不是MySql / Linux专家-您如何从一个网站获得100多个连接?我只做asp.net,我的任何页面一次只能打开一个连接-因此,这意味着同时处理100多个页面(实际上更多的是页面仅在需要时打开连接)。我将研究您处理连接的方法-效率极低。
TomTom

AWS会根据实例的大小设置最大连接数。他们使用的公式是:max_connections = {DBInstanceClassMemory / 12582880}请参阅参数组文档:https:

也许您应该考虑实现某种连接池。
mustaccio 2014年

Answers:


6

这是一个存储过程,可以杀死长时间运行的SELECT

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

要杀死运行时间超过30秒的SELECT,请运行此命令

CALL test.Kill_Long_Running_Selects(30,0);

如果要查看连接被终止,请运行此命令

CALL test.Kill_Long_Running_Selects(30,1);

也许您可以创建一个MySQL事件来每分钟调用一次此存储过程。

如果Amazon不让您拥有EVENT特权,则必须在EC2服务器上编写一个外部Shell脚本以连接到数据库并运行存储过程。该shell脚本可以放入crontab中。

如果Amazon不让您拥有PROCESSSUPER特权,则可能需要将数据库移出RDS并移至另一个运行MySQL的EC2实例中,以实现此目的。然后,您可以创建不受Amazon托管限制的MySQL事件。


1
这是一个很好的答案!我今天在RDS上使用了它,只需更改KILL @kill_id行;“调用mysql.rds_kill(@kill_id);” 而且效果很好。
Dave R

@DaveR谢谢。我将在今天晚些时候更新该行。
RolandoMySQLDBA

@DaveR我刚刚进行了更改。感谢您指出了这一点。
RolandoMySQLDBA '17年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.