PHP连接远程MySQL需两端协同:MySQL端须修改bind-address为0.0.0.0、创建限定IP用户并授权、防火墙仅放行PHP服务器IP;PHP端用PDO指定charset和异常模式,密码从环境变量读取,并按telnet→用户检查→日志→命令行顺序排查。

PHP独立环境连接远程MySQL,核心是两端协同:MySQL服务器要“放行”,PHP代码要“找对门”。不是改几行代码就能通,也不是只开个端口就安全。关键在配置闭环和权限收敛。
MySQL服务器端必须做的三件事
远程连接失败,八成卡在这一步。不能只改bind-address就以为万事大吉。
-
监听地址放开:编辑
/etc/mysql/mysql.conf.d/mysqld.cnf(Ubuntu/Debian)或/etc/my.cnf(CentOS),把bind-address = 127.0.0.1改为bind-address = 0.0.0.0;重启服务:sudo systemctl restart mysql -
创建限定IP的用户:不要用
'user'@'%'。假设你的PHP服务器公网IP是203.0.113.45,执行:CREATE USER 'webapp'@'203.0.113.45' IDENTIFIED BY 'StrongP@ss2026';GRANT SELECT,INSERT,UPDATE ON myapp_db.* TO 'webapp'@'203.0.113.45';FLUSH PRIVILEGES; -
开放3306并限制来源:用
ufw(Ubuntu)或firewalld(CentOS)只放行PHP服务器IP:sudo ufw allow from 203.0.113.45 to any port 3306
PHP端连接代码与安全要点
用PDO比mysqli更稳妥,错误可控、预处理天然支持、字符集易统一。
-
连接字符串明确指定charset:避免乱码,也防止部分注入绕过:
$dsn = 'mysql:host=203.0.113.45;dbname=myapp_db;charset=utf8mb4'; -
启用异常模式+关闭错误显示:生产环境绝不能暴露数据库结构或凭证:
$pdo = new PDO($dsn, $user, $pass, [<br> PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,<br> PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC<br>]);
-
密码不硬编码:从环境变量或配置文件(不在Web根目录)读取:
$pass = $_ENV['DB_PASSWORD'] ?? file_get_contents('/etc/secrets/db_pass');
连不通?按顺序快速排查
别一上来就查PHP代码。网络层和数据库层的问题占九成。
立即学习“PHP免费学习笔记(深入)”;
- 从PHP服务器执行:
telnet 203.0.113.45 3306—— 看是否能建立TCP连接 - 登录MySQL服务器,运行:
SELECT user, host FROM mysql.user WHERE user = 'webapp';—— 确认host值精确匹配PHP服务器IP - 检查MySQL错误日志:
sudo tail -f /var/log/mysql/error.log—— 常见如“Host ... is not allowed to connect”直接定位权限问题 - 临时用命令行验证连接:
mysql -h 203.0.113.45 -u webapp -p myapp_db—— 绕过PHP,确认凭据和网络本身可用
进阶建议:分离后更稳更安全
数据库真分离了,就不能再当本地服务用。得补上运维习惯。
-
强制SSL连接:在MySQL中启用
require_secure_transport = ON,PDO连接串加&sslmode=require -
读写分离预备:即使当前单库,PDO连接参数可预留
readhost/writehost逻辑,为后续扩展留接口 -
连接池意识:避免脚本内反复new PDO;用连接复用或长连接(
PDO::ATTR_PERSISTENT => true),但注意事务隔离风险



















