【问题标题】:Tracking down MySQL connection leaks追踪 MySQL 连接泄漏
【发布时间】:2010-01-19 16:04:58
【问题描述】:

我有一个应用程序服务器(Linux 机器上的 jetty 6)托管 15 个个人应用程序(个人战争)。每隔 3 或 4 天,我就会收到来自 nagios 的关于打开的 TCP 连接数的警报。经过检查,我发现这些连接中的绝大多数都是到 MySQL 服务器的。

netstat -ntu | grep TIME_WAIT

在 MySQL 服务器上显示来自应用程序服务器的 10,000 多个连接(注意状态为 TIME_WAIT)。如果我重新启动码头,连接将下降到几乎为零。

节目状态中的一些有趣的值:

mysql> show status;
+--------------------------+-----------+
| Variable_name            | Value     |
+--------------------------+-----------+
| Aborted_clients          | 244       |
| Aborted_connects         | 695853860 |
| Connections              | 697203154 |
| Max_used_connections     | 77        |
+--------------------------+-----------+

“显示进程列表”不会显示任何异常(这是我所期望的,因为大多数连接都是空闲的 - 请记住上面的 TIME_WAIT 状态)。

我有一个用于此服务器的测试环境,但它从来没有任何问题。它显然不会获得太多流量,并且应用程序服务器不断重新启动,因此调试没有太大帮助。我想我可以深入研究每个单独的应用程序并编写一个负载测试来访问数据库代码,但这会花费很多时间/麻烦。

我有什么想法可以追踪抓住所有这些连接并且永不放弃的应用程序吗?

【问题讨论】:

    标签: mysql linux


    【解决方案1】:

    答案似乎是在 [mysqld] 下的 my.cnf 中添加以下条目 :

    wait_timeout=60
    interactive_timeout=60
    

    我在这里找到它(一直在底部):http://community.livejournal.com/mysql/82879.html

    终止陈旧连接的默认等待时间为 22800 秒。 验证:

    mysql> show variables like 'wait_%';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | wait_timeout  | 60    |
    +---------------+-------+
    

    编辑:我忘了提,我还在 /etc/sysctl.conf 中添加了以下内容:

    net.ipv4.tcp_fin_timeout = 15
    

    这应该有助于降低操作系统在重用连接资源之前等待的阈值。

    编辑 2:/etc/init.d/mysql reload 不会真正重新加载您的 my.cnf(请参阅下面的链接)

    【讨论】:

    【解决方案2】:

    可能是连接池配置错误以保持太多连接,并且它们保持了太多空闲进程。

    除此之外,我能想到的只是某些代码保留了结果集,但这似乎不太可能。要捕获是否是超时的慢查询,您还可以将 MySQL 设置为写入 conf 文件中的慢查询日志,然后它将写入所有耗时超过 X 秒的查询,默认为 10 秒。

    【讨论】:

    • 我正在记录慢速查询,这似乎不是问题。我查看了连接池配置,它们对我来说看起来都很正常。池化机制差异很大(DBCP、蝴蝶持久性、Hibernate / JPA、bekeeper、iBatis 等),所以我对发现错误配置的能力并不完全有信心。
    【解决方案3】:

    嗯,我想到的一件事(虽然我不是这方面的专家)是增加对 mySQL 的日志记录并查找所有连接/关闭消息。如果这不起作用,您可以编写一个小型代理,放在实际的 mySQL 服务器和执行额外日志记录的应用程序套件之间,您将知道谁在连接/离开。

    【讨论】:

    • 我可以在 TEST 环境中执行此操作,但随后我又重新开始在 db 代码上编写负载测试(因此我可以在日志中获得一些活动)。我希望有一些 MySQL 魔法来跟踪与用户/模式/主机/等的死连接...
    • 为什么不增加生产服务器的日志记录?
    • 来自 my.cnf 正上方的日志记录部分“请注意,此日志类型是性能杀手。”此外,这将需要重新启动 PROD MySQL 服务器。由于这个数据库服务器托管了许多其他实时项目,我真的不能无谓地搞乱它。
    【解决方案4】:

    SHOW PROCESSLIST 显示每个线程的用户、主机和数据库。除非所有 15 个应用程序都使用相同的组合,否则您应该能够使用此信息进行区分。

    【讨论】:

    • 仅适用于实时连接 - 它不会显示陈旧的连接。
    【解决方案5】:

    我的客户端服务器上的 +30,000 TIME_WAIT 遇到了同样的问题。通过在/etc/sysctl.conf 中添加解决了该问题:

    net.ipv4.tcp_syncookies = 1 
    net.ipv4.tcp_tw_reuse = 1 
    net.ipv4.tcp_tw_recycle = 1 
    net.ipv4.tcp_fin_timeout = 30 
    

    然后:

    /sbin/sysctl -p
    

    2 或 3 分钟后,TIME_WAIT 连接数从 30 000 增加到 7 000。

    【讨论】:

      【解决方案6】:

      /proc/sys/net/ipv4/tcp_fin_timeout 在 RHEL7.tcp_tw_reuse 中为 60,tcp_tw_recycle 改为 1,性能提升。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-24
        • 1970-01-01
        • 2012-07-01
        • 1970-01-01
        • 2011-02-15
        • 2012-12-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多