问题描述
今天在一台新的服务器中安装了php7.2,mysql-5.6后。测试用php连接mysql时发现无论如何php都连接不上mysql数据库,排除了数据库账号错误,并且php已经安装了连接数据库的mysqlnd扩展。
问题排查
使用php连接测试脚本,查看到底是什么错误导致php连接不上mysql的。
以下是php连接mysql的php测试脚本db-connect-test.php
<?php
$dbname = 'mysql';
$dbuser = 'root';
$dbpass = '1234';
$dbhost = 'localhost';
$connect=mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
// 检查连接
if (!$connect)
{
die("连接错误: " . mysqli_connect_error());
}
die("连接成功...\n");
?>
注意观察php脚本中,$dbhost的值我给的是localhost,也就是使用socket进行连接数据库。
经过测试,发现PHP报错:No such file or directory in /root/mysql_connect_test.php on line 6
报错说db-connect-test.php中的第6行有问题,下面看下第8行的代码:
$connect=mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
mysqli_connect()
这是php连接数据库的一个函数,根据报错提示这里面缺少文件或目录。
mysqli_connect()
函数的参数有:host,username,password,dbname,port,socket。
在mysqli_connect()函数中,我已经加入了host,username,password,dbname这4个参数了。
经过调试,发现当我加入socket和port参数时,php就可以正常连接数据库了。
下面是加入了socket参数后的php脚本:
<?php
$dbname = 'mysql';
$dbuser = 'root';
$dbpass = '1234';
$dbhost = 'localhost';
$dbport = '3306';
$dbsocket = '/tmp/mysql.sock';
$connect=mysqli_connect($dbhost, $dbuser, $dbpass, $dbname, $dbport, $dbsocket);
// 检查连接
if (!$connect)
{
die("连接错误: " . mysqli_connect_error());
}
die("连接成功...\n");
?>
到这里可以分析出,php连接数据库的失败的原因很可能是数据库socket连接造成的。
为了证明这个结论,让PHP使用TCP/IP连接数据进行测试:
<?php
$dbname = 'mysql';
$dbuser = 'root';
$dbpass = '1234';
$dbhost = '127.0.0.1';
$connect=mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
// 检查连接
if (!$connect)
{
die("连接错误: " . mysqli_connect_error());
}
die("连接成功...\n");
?>
测试结果如下,可以看到使用TCP方式连接是可以成功的。
解决问题
- 查看mysql的socket文件
可以看到mysql使用的socket是/tmp/mysql.sock
mysql> show variables like "socket";
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| socket | /tmp/mysql.sock |
+---------------+-----------------+
1 row in set (0.00 sec)
- 查看php默认使用的mysql socket
发现php默认使用的mysql socket是 /var/mysql/mysql.sock
[root@centos ~]# php -r 'echo phpinfo();' | grep mysql.sock
mysqli.default_socket => /var/lib/mysql/mysql.sock => /var/lib/mysql/mysql.sock
pdo_mysql.default_socket => /var/lib/mysql/mysql.sock => /var/lib/mysql/mysql.sock
经过对比,发现php和mysql指定的数据库socket文件路径不一样,这可能也就是导致php在使用socket连接数据库时出错的原因。
这里先给出2个解决办法:
- 方法一:修改mysql的配置文件,配置socket与php的一致
[root@centos ~]# mkdir -p /var/lib/mysql
[root@centos ~]# chown -R mysql:mysql /var/lib/mysql
[root@centos ~]# vim /etc/my.cnf
[mysqld]
socket = /var/lib/mysql/mysql.sock
- 方法二:修改php的配置文件,配置socket与mysql的一致
更改php.ini中的 mysql.default_socket
、mysqli.default_socket
、pdo_mysql.default_socket
。但在PHP72版本中,php.ini配置文件中没有mysql.default_socket
,可以不进行设置此条配置。
[root@centos ~]# vim /etc/php.ini
mysqli.default_socket = /tmp/mysql.sock
pdo_mysql.default_socket = /tmp/mysql.sock
PHP72安装完后,会在bin目录下生成php-config、zts-php-config两个脚本文件,这连个脚本用于获取所安装的php配置的信息。这2个脚本中的socket路径也只默认为/var/lib/mysql/mysql.sock
修改脚这两个文件来制定mysql socket(可选,非必须修改):
[root@centos ~]# sed -i 's@--with-mysql-sock=/var/lib/mysql/mysql.sock@--with-mysql-sock=/tmp/mysql.sock@g' /bin/php-config
[root@centos ~]# sed -i 's@--with-mysql-sock=/var/lib/mysql/mysql.sock@--with-mysql-sock=/tmp/mysql.sock@g' /bin/zts-php-config
修改完配置再重启php-fpm后,php就可以使用socket的连接方式连接数据库了。