CentOS 7下PHP无法连接MariaDB socket的一个可能的解决方案

安装或编译完成LEMP之后,有些情况下总会出现莫名其妙的连接故障,如著名的502 Bad Gateway。产生连接问题的原因有些是Nginx配置文件写错,有些是PHP-FPM中分配的资源不足,但还有一些与PHP和MariaDB/MySQL的socket配置有关。CentOS 7对于tmp文件的路径设置方式与CentOS 6不同,全部采用系统默认配置很可能造成PHP代码程序无法连接MariaDB/MySQL。

CentOS 7中,MariaDB/MySQL的service文件有tmp目录是否为true的设置[1](以下为YUM安装的MySQL Community Server 5.5中默认的service启动文件),PrivateTmp参数设置为true则会在系统tmp目录下再生成一个单独的随机子目录来存储socket文件,这样PHP就无法通过php.ini配置文件中设置的路径找到对应的数据库socket。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[Unit]
Description=MySQL Community Server
After=network.target
After=syslog.target

[Install]
WantedBy=multi-user.target
Alias=mysql.service

[Service]
User=mysql
Group=mysql

# Execute pre and post scripts as root
PermissionsStartOnly=true

# Needed to create system tables etc.
ExecStartPre=/usr/bin/mysql-systemd-start pre

# Start main service
ExecStart=/usr/bin/mysqld_safe --basedir=/usr

# Don't signal startup success before a ping works
ExecStartPost=/usr/bin/mysql-systemd-start post

# Give up if ping don't get an answer
TimeoutSec=600

Restart=always
PrivateTmp=false

以YUM软件管理包方式安装的MariaDB/MySQL Server,socket文件默认路径是/var/lib/mysql/mysql.sock,在编译PHP或后期设置php.ini时,将其中涉及到MariaDB/MySQL的socket指向调整为该路径即可。或使用以下sed命令[2]直接处理后重新启动相关应用程序如PHP-FPM就可以了。

1
sed -i 's/mysqli.default_socket =/mysqli.default_socket=\/var\/lib\/mysql\/mysql.sock/g;s/pdo_mysql.default_socket=/pdo_mysql.default_socket=\/var\/lib\/mysql\/mysql.sock/g' /usr/local/php/lib/php.ini

同样的道理,在CentOS 6中如果使用PHP-FPM来配合Web服务器程序,一般PHP-FPM的socket文件是直接放置在系统tmp目录下的(如/tmp/php-fpm.sock),而在CentOS 7中PHP-FPM的socket文件默认是放置在系统tmp目录的一个随机子目录下(如/tmp/systemd-private-93ecae8ad897595cad25716dfa2de83e-php-fpm.service-s9PYjX),这就为Web服务器程序如Nginx连接PHP-FPM带来了困难。在Nginx服务器配置文件中,如果要使用效率更高的socket连接方式,则无法定位PHP-FPM的socket文件。从以上经验可知,可将PHP-FPM的socket文件路径修改为tmp以外的其它路径,如/dev/shm/php-fpm.sock,或将PHP-FPM的service启动文件中的PrivateTmp参数值修改为false,从而继续沿用传统的办法在Nginx配置文件中为PHP-FPM的连接指定/tmp/php-fpm.sock,或者改用非socket的TCP连接方式,将Nginx和PHP-FPM的连接配置统一调整为127.0.0.1:9000。


  1. Nginx官方提供的systemd启动文件样例包含PrivateTmp=true的默认设置。PHP(以7.2版为例)源码sapi/fpm目录下的php-fpm.service文件给出的默认设置也是PrivateTmp=true ↩︎

  2. 假设PHP编译时启用的数据库连接方式是PDO以及MySQLi ↩︎