首页 文章

PHP-MySQLi连接随机失败,并显示“无法分配请求的地址”

提问于
浏览
2

从大约2周开始,我正在处理LAMP堆栈中最奇怪的问题之一 . 长篇短信随机连接到MySQL服务器失败,并显示错误消息:

Warning:  mysqli::real_connect(): (HY000/2002): Cannot assign requested address in ..

MySQL处于不同的“盒子”,托管在Rackspace Cloud今天我们将它的版本降级为

Ver 14.14 Distrib 5.1.42, for debian-linux-gnu (x86_64).

根据它的状态变量,DB服务器非常忙于处理每秒查询数:5327.957 .

MySQL处于log-warnings = 9但没有记录连接拒绝的争用 . 站点和齿轮工作者脚本都会因为错误而失败,假设概率为1% . 没有服务器负载似乎不是我们监控的因素 . (CPU负载,IO负载或MySQL负载)最大数据库连接数(max_connections)设置为200但我们从未与数据库同时连接超过100个连接

它有和没有防火墙软件 .

我怀疑TCP网络问题而不是PHP / MySQL配置问题 .

任何人都可以告诉我如何找到它?

更新:

连接代码是:

$this->_mysqli = mysqli_init(); 
$this->_mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 120); 
$this->_mysqli->real_connect($dbHost,$dbUserName, $dbPassword, $dbName); 

if (!is_null($this->_mysqli->connect_error)) {
    $ping = $this->_mysqli->ping(); 

    if(!$ping){
        $error = 'HOST: {'.$dbHost.'};MESSAGE: '. $this->_mysqli->connect_error ."\n"; 
        DataStoreException::raiseHostUnreachable($error);
    }
}

4 回答

  • 6

    使用Vicidial我经常遇到同样的问题,由于所使用的编程类型,必须(非常)频繁地从许多vicidial组件 Build 新的MYSQL连接,我们有系统锤击数据库服务器每秒超过10000个连接,其中大部分都在几毫秒内完成服务,并在一秒或更短的时间内关闭 . 根据经验,我可以告诉您,在本地网络中,几乎没有丢失的软件包,tcp_fin_timeout可以一直降低到3而不会出现任何问题 .

    用于诊断等待关闭的连接是否是您的问题的典型linux命令是:

    netstat -anlp | grep :3306 | grep TIME_WAIT -wc
    

    这将显示等待完全关闭的连接数 .

    netstat -nat | awk {'print $5'} | cut -d ":" -f1 | sort | uniq -c | sort -n
    

    它将显示每个连接主机的连接,允许您识别哪个其他主机正在折叠您的系统(如果有多个候选者) .

    要测试修复,你可以

    cat /proc/sys/net/ipv4/tcp_fin_timeout
    echo "3" > /proc/sys/net/ipv4/tcp_fin_timeout
    

    这将暂时将tcp_fin_timeout设置为3秒,并告诉您它之前的秒数,因此您可以恢复到旧值进行测试 .

    作为永久性修复,我建议您将以下行添加到/etc/sysctl.conf中

    net.ipv4.tcp_fin_timeout=3
    

    在一个良好的本地网络内,不应该造成任何麻烦,如果你遇到问题,例如因为丢包,你可以试试

    net.ipv4.tcp_tw_reuse=1
    net.ipv4.tcp_tw_recycle=0
    net.ipv4.tcp_fin_timeout=10
    

    Wiche允许更多时间连接关闭并尝试重用相同的ip:端口组合,以便与同一主机:服务组合的新连接 .

    要么

    net.ipv4.tcp_tw_reuse=1
    net.ipv4.tcp_tw_recycle=1
    net.ipv4.tcp_fin_timeout=10
    

    哪个会更积极地尝试重用连接,但是可以通过您的网络服务器为其他应用程序创建新问题 . 所以你应该首先尝试简单的解决方案,在大多数情况下,它已经解决了你的问题,没有任何不良副作用!

    祝好运!

  • 8

    Vicidial服务器经常需要增加MySQL中的连接限制 . 许多安装(我们已经看到并在很多设备上工作)必须通过修改限制来实现

    此外,有报道称conntract_Max需要增加

    /sbin/sysctl -w net.netfilter.nf_conntrack_max=196608
    

    当问题变成网络相关时 .

    另请注意,Vicidial具有一些特定的建议设置,甚至还有一些用于mysql配置的企业设置 . 看看/ usr / src / astguiclient / conf中的my-bigvici.cnf中的一些配置想法可能会打开你的mysql服务器 .

    到目前为止,连接限制没有增加,只使用了额外的资源 . 由于服务器的目的是使该应用程序工作,因此将资源专用于此应用程序似乎不是问题 . 大声笑

  • 1

    我有这个问题,并使用持久连接模式解决了它,可以通过使用'p:'预先修复数据库主机名在mysqli中激活它

    $link = mysqli_connect('p:localhost', 'fake_user', 'my_password', 'my_db');
    

    来自:http://php.net/manual/en/mysqli.persistconns.php

    持久连接背后的想法是客户端进程和数据库之间的连接可以由客户端进程重用,而不是多次创建和销毁 . 这样可以减少每次需要时创建新连接的开销,因为未使用的连接已缓存并可以重复使用 . ...要打开持久连接,必须在连接时将p:添加到主机名 .

  • 17

    MySQL: Using giant number of connections

    频繁连接有什么危险?
    它运作良好,除了一些极端情况 . 如果您从同一个盒子每秒获得数百个连接,则可能会耗尽本地端口号 . 修复它的方法可能是 - 在linux上减少"/proc/sys/net/ipv4/tcp_fin_timeout"(这打破了TCP / IP标准,但你可能不关心你的本地网络),在客户端增加"/proc/sys/net/ipv4/ip_local_port_range" . 其他OS有类似的设置 . 您也可以为同一个数据库主机使用更多Web框或多个IP来解决此问题 . 我真的在 生产环境 中看到了这一点 .

    关于这个问题的一些背景:
    TCP / IP连接由localip:localport标识remoteip:远程端口 . 在这种情况下,我们有MySQL IP和端口以及客户端IP固定,所以我们只能改变有限范围的本地端口 . 注意 even after you close connection TCP/IP stack has to keep the port reserved for some time ,这是tcp_fin_timeout来自的地方 .

相关问题