问题描述

今天在一台新的服务器中安装了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_connect_mysql-1.png

经过测试,发现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方式连接是可以成功的。

php_connect_mysql-2.png

 

错误解决

  • 查看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

$ 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的一致
$ mkdir -p /var/lib/mysql
$ vim /etc/my.cnf
[mysqld]
socket = /var/lib/mysql/mysql.sock
  • 方法二:修改php的配置文件,配置socket与mysql的一致

更改php.ini中的 mysql.default_socketmysqli.default_socketpdo_mysql.default_socket。但在PHP72版本中,php.ini配置文件中没有mysql.default_socket,可以不进行设置此条配置。

$ 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(可选,非必须修改):

$ sed -i 's@--with-mysql-sock=/var/lib/mysql/mysql.sock@--with-mysql-sock=/tmp/mysql.sock@g' /bin/php-config
$ 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的连接方式连接数据库了。