mysqli_connect()连不上远程MySQL主因是MySQL服务端未放行:需将bind-address设为0.0.0.0、创建'用户'@'PHP服务器IP'授权、放行3306端口(防火墙及云安全组),且PHP中host必须用公网IP而非localhost或域名。

mysqli_connect() 连不上远程 MySQL,大概率不是代码问题
PHP 8.5.5 的 mysqli 扩展本身完全支持远程连接,但绝大多数“连不上”报错(比如 Host 'x.x.x.x' is not allowed to connect 或直接超时)根本不在 PHP 层。MySQL 服务端默认只监听 127.0.0.1,相当于把门焊死了——你代码填对 IP 和密码也没用。
必须先确认三件事:
- MySQL 配置里
bind-address是0.0.0.0(或明确包含你的 PHP 服务器公网 IP),不是127.0.0.1 - MySQL 用户是用
'user'@'php-server-ip'形式创建的,不是'user'@'localhost'或粗暴地改成'user'@'%' - 3306 端口在 MySQL 服务器的防火墙(
ufw、iptables)和云平台安全组(GCP/AWS/腾讯云)都已放行,且源 IP 限定为你的 PHP 服务器 IP
mysqli 构造函数参数必须用公网 IP,别信 localhost 或域名
new mysqli($host, $username, $password, $database) 的第一个参数 $host 填 localhost 在远程场景下必然失败;填域名看似方便,但 DNS 解析失败或延迟会导致连接卡住几秒才报错,错误信息还不直观。
直接用 MySQL 服务器的**公网 IPv4 地址**(例如 34.123.45.67),绕过所有中间环节:
立即学习“PHP免费学习笔记(深入)”;
$host = '34.123.45.67'; // 不是 'localhost',也不是 'db.example.com'
$username = 'app_user';
$password = 'strong_password';
$database = 'mydb';
$conn = new mysqli($host, $username, $password, $database);
if ($conn->connect_error) {
die('连接失败: ' . $conn->connect_errno . ' – ' . $conn->connect_error);
}
注意:PHP 8.5.5 中 mysqli 默认不自动设置字符集,中文乱码常见。建议手动执行:$conn->set_charset('utf8mb4');,放在连接成功判断之后。
连接失败时,优先用 telnet 或 nc 验证端口连通性
别急着改 PHP 代码。先从 PHP 服务器机器上验证网络层是否通:
-
telnet 34.123.45.67 3306—— 如果显示Connected to...,说明端口可达;如果卡住或报Connection refused,就是 MySQL 没监听或防火墙拦了 -
nc -zv 34.123.45.67 3306—— 更轻量,输出更明确 - 如果
telnet通但 PHP 还连不上,再查 MySQL 用户权限:登录 MySQL 服务端执行SELECT host, user FROM mysql.user WHERE user = 'app_user';,确认返回的host字段值是你 PHP 服务器的精确 IP,不是localhost或空字符串
PHP 8.5.5 下 mysqli 的几个实际细节
PHP 8.5.5 对 mysqli 没做破坏性变更,但有几个容易忽略的点:
-
mysqli扩展必须启用:检查phpinfo()是否列出mysqli,或运行php -m | grep mysqli;若无,需在php.ini中取消;extension=mysqli的注释并重启 Web 服务 - 连接超时默认是 60 秒,太长。可在构造后立即设:
$conn->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5); - 不要用
@mysqli_connect(...)抑制错误——它会掩盖真实的连接失败原因,改用异常模式或显式判断$conn->connect_error - 如果 MySQL 启用了 SSL,而你没配证书,
mysqli会静默失败。此时需显式禁用:$conn->ssl_set(null, null, null, null, null);(仅调试用,生产环境应配 SSL)
真正卡住人的从来不是 new mysqli() 这一行代码,而是 MySQL 服务端那几行配置、那个用户授权语句、以及云平台安全组里漏掉的一条规则——它们全得在 PHP 运行前就配好,且相互匹配。



















