【问题标题】:MySql Proccesslist filled with "Sleep" Entries leading to "Too many Connections"?MySql 进程列表充满了“睡眠”条目导致“连接太多”?
【发布时间】:2010-03-09 09:02:57
【问题描述】:

我想就一个长期存在的 php/mysql 连接问题寻求您的帮助。

每次我执行“SHOW PROCESSLIST”命令时,它都会显示大约 400 个空闲(状态:睡眠)连接到来自我们的 5 个 Web 服务器的数据库服务器。

这从来都不是什么大问题(而且我没有找到快速的解决方案),直到最近流量增加,从那时起 MySQL 反复报告“to many connections”问题,即使这些连接中有 350 多个在“睡眠”状态。即使与同一台服务器存在休眠连接,服务器也无法获得 MySQL 连接。

当 apache 服务器重新启动时,所有这些连接都会消失。

用于创建数据库连接的 PHP 代码使用普通的“mysql”模块、“mysqli”模块、PEAR::DB 和 Zend Framework Db 适配器。 (不同的项目)。没有一个项目使用持久连接。

提高连接限制是可能的,但似乎不是一个好的解决方案,因为它现在是 450,而且一次只有 20-100 个“真实”连接。

我的问题:

为什么有这么多处于睡眠状态的连接,我该如何防止呢?

-- 更新:

一次运行的 Apache 请求的数量从不超过 50 个并发请求,所以我猜是关闭连接有问题,或者 apache 在没有附加 phpscript 或其他东西的情况下保持端口打开(?)

my.cnf 以防万一:

innodb_buffer_pool_size = 1024M

max_allowed_packet = 5M
net_buffer_length = 8K

read_buffer_size = 2M
read_rnd_buffer_size = 8M

query_cache_size = 512M
myisam_sort_buffer_size = 128M

max_connections = 450
thread_cache = 50
key_buffer_size = 1280M
join_buffer_size = 16M

table_cache = 2048
sort_buffer_size = 64M
tmp_table_size = 512M
max_heap_table_size = 512M

thread_concurrency = 8

log-slow-queries = /daten/mysql-log/slow-log
long_query_time = 1
log_queries_not_using_indexes

innodb_additional_mem_pool_size = 64M
innodb_log_file_size = 64M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    基本上,您会在以下情况下获得处于睡眠状态的连接:

    • 一个 PHP 脚本连接到 MySQL
    • 执行了一些查询
    • 然后,PHP 脚本会做一些需要时间的事情
      • 无需断开与数据库的连接
    • 最后,PHP 脚本结束
      • 这意味着它与 MySQL 服务器断开连接

    因此,当您有许多 PHP 进程保持连接时,通常会导致许多进程处于睡眠状态,而实际上并没有在数据库端执行任何操作。

    一个基本的想法,所以:确保您的 PHP 进程没有运行太久——或者一旦它们不再需要访问数据库就强制它们断开连接。


    另一件事,我经常在服务器上有负载时看到:

    • 有越来越多的请求来到 Apache
      • 这意味着要生成许多页面
    • 每个 PHP 脚本为了生成一个页面,都会连接到数据库并执行一些查询
    • 随着数据库服务器负载的增加,这些查询会花费越来越多的时间
    • 这意味着更多的进程不断堆积

    一个可以提供帮助的解决方案是减少您的查询所花费的时间——优化最长的查询。

    【讨论】:

    • 非常感谢您的评论!然而问题是,即使所有的网络服务器结合在一起,也没有接近 400 个请求在运行。在创建连接的请求完成后,“睡眠”状态会继续。例如。在每秒浏览量不超过 1 次的午夜,问题也会出现。
    • 这很奇怪...哦,也许是一个想法:您使用的是永久连接吗? (例如mysql_pconnect 函数)
    • 哦 :-( 太糟糕了 :-( ;; 出于好奇,当这种情况发生时,您是否还有仍然存在的“幽灵”httpd 进程,什么也不做?
    • 我认为您需要再次寻找持久连接,Zend 和 PDO 都没有使用带有 'pconnect' 的语法来实现持久连接。
    • 提醒一下:基于 PDO 的驱动程序也可以 pconnect,但他们不这么称呼它。它是使用 setOption 方法在数据库句柄上设置的选项。
    【解决方案2】:

    上述解决方案如运行查询

    SET session wait_timeout=600;
    

    只有在 mysql 重新启动后才能工作。对于持久解决方案,编辑 mysql.conf 并在 [mysqld] 之后添加:

    wait_timeout=300
    interactive_timeout = 300
    

    其中 300 是您想要的秒数。

    【讨论】:

      【解决方案3】:

      增加最大连接数并不能解决问题。

      我们在服务器上遇到了同样的情况。这就是发生的事情

      用户打开一个页面/视图,连接到数据库,查询数据库,仍然查询(查询)没有完成,用户离开页面或移动到其他页面。 因此,如果有更多用户连接到数据库并执行类似操作,则已打开的连接将保持打开状态,并保持连接数增加。

      你可以设置interactive_timeout MySQL,默认是28800(8小时)到1小时

      SET interactive_timeout=3600
      

      【讨论】:

        【解决方案4】:

        在增加 max_connections 变量之前,您必须通过运行 show processlist 命令检查您有多少非交互式连接。

        如果你有很多睡眠连接,你必须减少“wait_timeout”变量的值,等待一段时间后关闭非交互式连接。

        • 显示 wait_timeout 值:

        显示会话变量,例如“wait_timeout”;

        +----------------+-------+

        |变量名 |价值 |

        +----------------+-------+

        |等待超时 | 28800 |

        +----------------+-------+

        数值以秒为单位,表示非交互连接仍长达8小时。

        • 更改“wait_timeout”变量的值:

        SET 会话 wait_timeout=600; 查询正常,0 行受影响(0.00 秒)

        10 分钟后,如果 sleep 连接仍在休眠,则 mysql 或 MariaDB 会断开该连接。

        【讨论】:

          【解决方案5】:

          所以我同时运行 300 个 PHP 进程,并且获得的速率在每秒 60 到 90 个之间(我的进程涉及 3 次查询)。我将它提高到 400,然后下降到每秒大约 40-50。我把它降到了 200,现在又回到了 60 到 90 之间!

          所以我对任何有这个问题的人的建议是尝试运行less而不是更多,看看它是否有所改善。将使用更少的内存和 CPU,因此运行的进程将具有更大的能力并且速度可能会提高。

          【讨论】:

            【解决方案6】:

            好吧,所以在尝试了所有解决方案来解决 wordpress 博客上的这个确切问题之后,我可能做了一些非常愚蠢或天才的事情......不知道为什么 Mysql 连接增加了,我使用了 php 脚本在我的标题下方杀死所有睡眠进程..

            因此,我网站的每个访问者都有助于杀死睡眠进程..

            <?php
            $result = mysql_query("SHOW processlist");
            while ($myrow = mysql_fetch_assoc($result)) {
            if ($myrow['Command'] == "Sleep") {
            mysql_query("KILL {$myrow['Id']}");}
            }
            ?>
            

            【讨论】:

            • 这是个坏主意——你怎么知道php脚本已经使用mysql连接了?它可能会完成一个查询,进入睡眠状态执行一些 php,然后稍后需要另一个查询。
            • 你测试了吗?因为如果它不是插件,那么 wordpress 不需要任何睡眠进程......测试它并告诉我。
            • 外壳版本:mysql -e "show full processlist;" -ss | grep Sleep | awk '{print "KILL "$1";"}' | mysql
            • 你找到跟踪睡眠命令来源的方法了吗?顺便说一句,您的代码很棒,谢谢
            • 如果你打算这样做,而不是找到根本原因(更好的路线),我建议考虑连接已经休眠了多长时间,这样你访问合法运行的连接的可能性要小得多。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-16
            • 2013-05-17
            • 1970-01-01
            • 1970-01-01
            • 2011-08-13
            • 2013-11-01
            相关资源
            最近更新 更多