mysqli不能使用localhost,请问这是怎么回事?

代码如下:

<?php
$mysqli = new mysqli('localhost', 'root', '184995511', 'cg_levi');
if ($mysqli->connect_error) {
    die('Connect Error (' . $mysqli->connect_errno . ') '
            . $mysqli->connect_error);
};

echo 'ok';
  • 如果上面连接地址为'localhost'就会报错,如下:

    Warning: mysqli::mysqli(): (HY000/2002): No such file or directory in /mnt/www/cglevi/publichtml/mysql.php on line 2 Connect Error (2002) No such file or directory

  • 将'localhost'修改为'127.0.0.1'之后链接正常

查看了hosts没有问题,如下:

127.0.0.1 localhost
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
/etc/hosts (END) 

查看mysql状态,没有问题,如下:

mysql> status;
--------------
mysql  Ver 14.14 Distrib 5.6.10, for Linux (x86_64) using  EditLine wrapper

Connection id:      860
Current database:   
Current user:       root@localhost
SSL:            Not in use
Current pager:      stdout
Using outfile:      ''
Using delimiter:    ;
Server version:     5.6.10 MySQL Community Server (GPL)
Protocol version:   10
Connection:     Localhost via UNIX socket
Server characterset:    latin1
Db     characterset:    latin1
Client characterset:    utf8
Conn.  characterset:    utf8
UNIX socket:        /var/lib/mysql/mysql.sock
Uptime:         13 hours 13 min 50 sec

Threads: 1  Questions: 11900  Slow queries: 0  Opens: 100  Flush tables: 1  Open tables: 80  Queries per second avg: 0.249
--------------

请问如何解决?

阅读 32.6k
3 个回答

开始的回答有点不严谨,估计也没有解决问题,修改了答案:

问题出现的原因:

当主机填写为localhost时MySQL会采用 unix domain socket连接,当主机填写为127.0.0.1时MySQL会采用TCP/IP的方式连接。使用Unix socket的连接比TCP/IP的连接更加快速与安全。这是MySQL连接的特性,可以参考官方文档的说明4.2.2. Connecting to the MySQL Server

On Unix, MySQL programs treat the host name localhost specially, in a way that is 
likely different from what you expect compared to other network-based programs. 
For connections to localhost, MySQL programs attempt to connect to the local server 
by using a Unix socket file. This occurs even if a --port or -P option is given to 
specify a port number. To ensure that the client makes a TCP/IP connection to the 
local server, use --host or -h to specify a host name value of 127.0.0.1, or the IP 
address or name of the local server. You can also specify the connection protocol 
explicitly, even for localhost, by using the --protocol=TCP option.

这个问题有以下几种解决方法:

  1. 使用TCP/IP代替Unix socket。即在连接的时候将localhost换成127.0.0.1。
  2. 修改MySQL的配置文件my.cnf,指定mysql.socket的位置:

    /var/lib/mysql/mysql.sock (你的mysql.socket路径)。

  3. 直接在php建立连接的时候指定my.socket的位置(官方文档:mysqli_connect)。比如:

    $db = new MySQLi('localhost', 'root', 'root', 'my_db', '3306', '/var/run/mysqld/mysqld.sock')

如果哪里没有说清楚或者说错了,欢迎提出了~~

我也碰到了这个问题,解决了,也搞明白了。

unix系统下连接mysql的方式有两种,一种是TCP,一种是socket;TCP是所有系统都支持的,通过TCP/IP协议可以访问本地和远程server,socket只有unix系统支持(windows不支持),通过Unix socket file只能访问本地server。

通过 --host 参数可以指定主机,默认情况下输入ip地址即通过TCP方式连,输入localhost或者不指定默认即通过socket连。

如:

1、mysql --host=127.0.0.1 -u root -p     #通过TCP连接
2、mysql --host=localhost -u root -p     #通过socket连
3、mysql -u root -p    #通过socket连

第二种情况,还有一个参数可以强制覆盖这个默认情况,--protocol 参数可以指定连接方式,如果第2、3种情况加上 --protocol=TCP,那么就覆盖默认方式,通过TCP连

4、mysql --host=localhost --protocol=TCP -u root -p    #通过TCP连接

那么问题就清楚了:通过127.0.0.1连没问题,说明TCP连接没问题,localhost有问题,是socket连接有问题。
通过socket连接是通过Unix socket file来连接,先得弄明白这个文件是啥?在哪?

通过客户端连接MySQL,不指定--host默认用socket来连。

mysql -u root -p

连接后,输入status;命令,可以看到有一行

Connection:        Localhost via UNIX socket

下面还有一行

UNIX socket:        /var/run/mysqld/mysqld.sock

这个就是socket文件的位置,通过 my.cnf文件里配置的。

PHP报的错误是No such file or directory,也就是说PHP找不到这个socket文件,那么PHP去哪找了?看手册:

mysqli::__construct ([ string $host = ini_get("mysqli.default_host") [, string $username = ini_get("mysqli.default_user") [, string $passwd = ini_get("mysqli.default_pw") [, string $dbname = "" [, int $port = ini_get("mysqli.default_port") [, string $socket = ini_get("mysqli.default_socket") ]]]]]] )

所有参数都是可选参数,如果不指定,默认会从ini配置文件去读。那这个默认值是什么呢? 在php.ini里找到mysqli.default_socket这一行,我的这里是空值。

解决方案有两个:
一个是调用的时候,参数全部指定,如:

$db = new mysqli('localhost','uname','passwd','dbname','3306','/var/run/mysqld/mysqld.sock');

另一个是修改php.ini文件,找到mysqli.default_socket= ,修改为

mysqli.default_socket=/var/run/mysqld/mysqld.sock

重启php-fpm。

推荐问题
宣传栏