现象1
在PHP error log里发现:
PHP Warning: mysqli::mysqli(): (HY000/2003): Can’t connect to MySQL server on ‘XXX.XXX.XXX.XXX’ (99) in /u1/www/XXXX.php on line 10
PHP Warning: mysqli::close(): Couldn’t fetch mysqli in /u1/www/XXXX.php on line 11
推断:只有在高并发的环境下出现
诊断分析:
通过MySQL数据库上抓包,没发现异常。又把目标转到php 服务器上。
BTW:
linux开着selinux连接MySQL在测试中基本上属于1ms+,禁掉selinux后在0.96左右。selinux还是要禁掉的。
既然又怀疑是PHP的问题就写一个程序测试(禁掉selinux后):
cat tconn.php
代码如下 | 复制代码 |
function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } $time_start = microtime_float(); for ( $i=0; $i<30000; $i++){ $dbh=new mysqli("XXX.XXX.XXX.XXX", "wubx", "wubxwubx", "userdb", 3308); $dbh->close(); } $time_end= microtime_float(); $time_use= ($time_end - $time_start)/30000; print "$time_usen"; #php tconn.php 0.00090954260031382 |
再次运行就开始大量的报错。
PHP Warning: mysqli::mysqli(): (HY000/2003): Can't connect to MySQL server on 'XXX.XXX.XXX.XXX' (99) in /u1/www/XXXX.php on line 10
PHP Warning: mysqli::close(): Couldn't fetch mysqli in /u1/www/XXXX.php on line 11
中止该程序后,通过
#strace php tconn.php 运行
得到:
connect(3, {sa_family=AF_INET, sin_port=htons(3308), sin_addr=inet_addr("XXX.XXX.XXX.XXX")}, 16) = -1 EADDRNOTAVAIL (Cannot assign requested address)
shutdown(3, 2 /* send and receive */) = -1 ENOTCONN (Transport endpoint is not connected)
看到这个大概明白是本地的网络可能注册不上了,也难怪在MySQL抓包看也正常。
看样子是本地tcp不能重用造成的。改一下在测试
代码如下 | 复制代码 |
sysctl -w net.ipv4.tcp_tw_reuse=1; |
在次测试问题不存在了。在这个上面碰了一下后顺便改一下/etc/sysctl.conf添加:
代码如下 | 复制代码 |
net.ipv4.tcp_max_syn_backlog = 819200 net.core.netdev_max_backlog = 400000 net.core.somaxconn = 4096 net.ipv4.tcp_tw_reuse=1 net.ipv4.tcp_tw_recycle=0 #sysctl -p |
问题解决
现象2
MYSQL.测试连接mysql 提示'Fatal error: Call to undefined function mysql_connect()"环境j是:windows xp sp2 en , apache2.2,mysql5.1rc.php5.28。
这个提示,会不会是php没有加载到连接mysql的库文件呢? 在启动apache server后.我试着删除'php5ts.dll'和'libmysql.dll'.提示不能删除.说明有程序在用着这两个库文件.说明是有加载的.(当然有许多方法来测试.比如可以用一些软件,查看程序服务加载的所有库文件.也是可以然而ap也说指是php.ini设置有问题.那我就不看别的.我就重点针对php.ini配置.
在没有迷信php.ini是正确下.终于发现.php.ini中漏了这一行.
PHPIniDir "你的php目录"
#(例如: PHPIniDir "c:/php")
重启apache server,然后.用网上常用的方法
以下为引用的内容:
代码如下 | 复制代码 |
<?php $link=mysql_connect('localhost','用户名','password'); if(!$link) echo "失败!"; else echo "成功!"; mysql_close(); ?> |
测试一下.就可以了
总结一下这些问题
1. 首先要排查网络问题和防火墙的问题
这个是必须的, 你要是连MySQL的服务器都连不上, 那还访问什么? 怎么检查呢? ping一下 ping 192.168.0.11 ping 的通的话, 再去检查一下 3306端口是不是被防火墙给挡掉了 ping 192.168.0.11:3306 或者干脆把防火墙关掉,service iptables stop (Redhat ) 或 ufw disable(ubuntu) 这一步没问题的话, 开始下一步:
2. 要排查有没有访问权限
说到访问权限, MySQL分配用户的时候会指定一个host, 比如我的 host 指定为 192.168.0.5 , 那么这个账号就只能 .5 这一台机器访问, 其他的机器用这个账号访问会提示没有权限。 host 指定为 % 则表示允许所有的机器访问。 一般来说出于安全方面的考虑,遵循最小权限原则, 权限的问题就不多讲了, 不会的自己查手册。 确定了权限没问题的话进行下一步:
3. 要排查MySQL的配置
检查mysql的配置文件, Linux下MySQL的配置文件叫 my.cnf windows下的叫 my.ini,检查这个配置项: –bind-address=IP
引用手册里的一段话:
The IP address to bind to. Only one address can be selected. If this option is specified multiple times, the last address given is used. If no address or 0.0.0.0 is specified, the server listens on all interfaces.
绑定的IP, 只能绑定一个IP, 如果绑定多个IP, 则以最后一个绑定的为准。 如果没有绑定或绑定 0.0.0.0, 服务器监听所有的客户端。
我曾经就被这个东西害惨过, 有一次搞了一个下午没搞定, 检查网络通的, 检查权限没问题, 客户端就是死活连不上, 一看手册明白了。 所以有什么问题还是要多看手册