特定场景下PHP无法解析MySQL容器名称的连接异常问题
解决mysqli连接的两个常见错误
咱们先把你遇到的两个问题拆开来看,其实都是因为对mysqli的连接逻辑理解有偏差导致的:
第一个错误:主机名解析失败(getaddrinfo failed)
Warning: mysqli::real_connect(): php_network_getaddresses: getaddrinfo failed: Name or service not known
这个错误的核心原因是:mysqli并不支持PDO风格的mysql://username:password@db_hostname/dbname格式DSN字符串。如果你直接把这个DSN当作主机名参数传给mysqli的连接方法,它会把整个字符串当成主机名去尝试解析,自然找不到对应的网络地址,就抛出了这个错误。
第二个错误:空用户权限被拒(Access denied)
Warning: mysqli::real_connect(): (HY000/1045): Access denied for user ''@'172.21.0.3' (using password:
你手动调用mysqli::real_connect("db_hostname")时,只传递了主机名参数,没有传入用户名和密码。mysqli在这种情况下会默认使用空用户名去连接数据库,而你的数据库服务器显然没有授权空用户从172.21.0.3这个IP访问,所以触发了1045权限错误。
正确的解决方案:解析DSN后连接
如果你的配置里只能用这种PDO风格的DSN,那我们可以手动解析DSN,提取出各个连接参数后再传给mysqli:
// 你的原始DSN字符串 $dsn = 'mysql://username:password@db_hostname/dbname'; // 用parse_url解析DSN,拆分出各个部分 $dsnParts = parse_url($dsn); // 提取必要的连接参数 $dbUser = $dsnParts['user']; $dbPass = $dsnParts['pass']; $dbHost = $dsnParts['host']; // 路径部分开头的/要去掉,剩下的就是数据库名 $dbName = ltrim($dsnParts['path'], '/'); // 初始化mysqli并建立连接 $mysqli = new mysqli(); $connectionSuccess = $mysqli->real_connect( $dbHost, $dbUser, $dbPass, $dbName ); // 检查连接结果 if (!$connectionSuccess) { die("连接失败: " . $mysqli->connect_error); }
额外注意事项
- 确认
db_hostname在你的环境中可以正常解析:比如在Docker容器环境中,要确保数据库容器和应用容器在同一个网络,且容器名可以被正确解析。 - 确认数据库用户的权限范围:比如如果应用容器的IP是
172.21.0.3,要确保数据库用户被授权从172.21.0.%或者%(任意IP)访问,授权语句类似:GRANT ALL ON dbname.* TO 'username'@'172.21.0.%' IDENTIFIED BY 'password';
内容的提问来源于stack exchange,提问作者Neka
相关产品推荐
相关产品推荐

