WordPress 连接非标准端口 MySQL 其实是个非常经典但容易让人踩坑的场景。很多人以为改个 wp-config.php 就能搞定,结果发现连上了数据库却死活进不去后台,或者报“Establishing a database connection”错误。
核心问题在于:WordPress 原生的 DB_HOST 配置项只支持主机名或 IP,不支持直接拼接端口号。 如果你写成 '127.0.0.1:3307',PHP 的 mysqli 或 PDO 驱动通常无法正确解析这个字符串,导致连接失败。
要解决这个问题,主要有三种靠谱的方案,按推荐程度排序:
方案一:使用 Unix Socket 或显式指定端口(最稳定)
这是官方文档中隐含支持的方式,但需要一点技巧。在 wp-config.php 中,DB_HOST 不仅仅接受主机名,它还接受一个数组格式(虽然文档没大肆宣传,但底层代码是支持的),或者通过修改 PHP 的 mysqli 默认行为。
步骤如下:
-
打开你的
wp-config.php文件。 -
找到
DB_HOST定义。 -
不要写成
'localhost:3307'或'127.0.0.1:3307'。 -
改为以下两种写法之一:
写法 A:显式指定端口(推荐)
define( 'DB_HOST', '127.0.0.1:3307' ); // 注意:这取决于你的 PHP 版本和 MySQL 驱动。 // 较新的 PHP 8.x + MySQLi 通常能自动识别冒号后的端口。 // 如果报错,请用写法 B。写法 B:通过 PHP 扩展参数传递(更稳妥)
WordPress 的wpdb类允许你在DB_HOST中使用特殊字符来触发不同的连接方式。但对于非标准端口,最通用的“黑客”做法是利用mysqli_real_connect的参数特性。不过,最简单且兼容性最好的方法是:实际上,对于大多数现代 LAMP/LNMP 环境,直接在
DB_HOST写127.0.0.1:3307是有效的,前提是:- 你使用的是
MySQLi扩展(PHP 默认)。 - 你没有强制使用
localhost(因为localhost会优先尝试 Unix Socket,而不是 TCP/IP,从而忽略端口)。
关键修正:
将DB_HOST从localhost改为127.0.0.1或具体的服务器 IP,并加上端口。define('DB_HOST', '127.0.0.1:3307');注意:这里必须用
127.0.0.1而不是localhost。因为localhost在 Linux/Unix 系统中默认走 Unix Socket 文件,而 Socket 文件通常绑定在标准路径上,不监听 TCP 端口。改成 IP 地址后,PHP 才会通过 TCP/IP 协议连接,此时才能识别端口号。 - 你使用的是
方案二:使用 SSH 隧道(最安全,适合云主机)
如果你的 MySQL 在非标准端口,且出于安全考虑只允许内网访问,或者你想避免暴露端口到公网,SSH 隧道是最佳实践。
原理:
本地机器 -> SSH 连接到云服务器 -> 转发本地某个端口(如 3306)到云服务器的 MySQL 端口(如 3307)。
操作步骤:
-
在你的本地电脑(开发机)上建立 SSH 隧道:
ssh -L 3306:127.0.0.1:3307 user@your-server-ip这条命令的意思是:把你本地的 3306 端口,通过 SSH 加密通道,转发到远程服务器的 127.0.0.1 的 3307 端口。
-
保持终端开启,然后正常配置 WordPress:
define('DB_HOST', 'localhost:3306'); // 或者直接用 localhost这样 WordPress 认为它连接的是本地标准端口,实际流量被 SSH 转发到了非标准端口。
优点:
- 无需修改 WordPress 核心代码逻辑。
- 数据加密传输,安全性高。
- 兼容性好,任何版本的 PHP/MySQL 都能用。
方案三:修改 MySQL 配置文件(不推荐,但最简单)
如果你能控制 MySQL 服务器本身,最直接的办法其实是把端口改回默认的 3306。
操作:
- 登录 MySQL 服务器。
- 编辑
/etc/mysql/my.cnf或/etc/my.cnf。 - 找到
port = 3307,改为port = 3306。 - 重启 MySQL 服务:
systemctl restart mysqld。
为什么我不推荐?
- 很多云厂商的安全组策略、防火墙规则可能已经针对特定端口做了限制。
- 如果同一台服务器上还有其他服务依赖非标准端口,改回去会影响其他服务。
- 违背了“最小权限原则”,非标准端口本身就是一种隐蔽性安全措施(Security through Obscurity)。
常见坑点排查
如果你改了 DB_HOST 还是连不上,请按以下顺序检查:
-
确认是
localhost还是127.0.0.1localhost-> Unix Socket -> 忽略端口 -> 失败。127.0.0.1-> TCP/IP -> 识别端口 -> 成功。- 务必确保
DB_HOST不以localhost开头。
-
检查 MySQL 是否监听该端口
netstat -tuln | grep 3307 # 或 ss -tuln | grep 3307确保输出中有
0.0.0.0:3307或:::3307,说明 MySQL 正在监听该端口。 -
检查防火墙/安全组
- 如果是云服务器(阿里云、腾讯云等),记得在控制台的安全组里放行 3307 端口的入方向规则,协议选择 TCP。
- 服务器内部的
iptables或firewalld也要放行。
-
PHP 错误日志
查看php-fpm.log或error_log,通常会给出类似:“Can’t connect to MySQL server on ‘127.0.0.1’ (111)”
这表示网络不通或端口不对。“Access denied for user…”
表示连接成功,但账号密码错。 -
SELinux(CentOS/RHEL 系统)
如果启用了 SELinux,可能会阻止 Apache/Nginx 进程连接非标准端口。可以尝试临时关闭测试:setenforce 0如果关闭后正常,则需要配置 SELinux 策略允许 httpd 连接网络端口:
setsebool -P httpd_can_network_connect_db 1
总结
对于生产环境,推荐使用方案一中的 127.0.0.1:3307 写法,并确保使用 127.0.0.1 而非 localhost。这是最直接、改动最小的方式。
如果涉及跨地域或高安全要求,方案二(SSH 隧道) 是更专业的选择,尤其适合开发和运维人员日常维护时使用。
云技术博客