php怎么连接MySQL数据库_php使用mysqli连接数据库教程【实战】

1次阅读

connection refused 错误主因是 mysql 服务未运行或端口被防火墙拦截,需先检查服务状态、端口监听(bind-address)、用户授权及认证插件兼容性。

php怎么连接MySQL数据库_php使用mysqli连接数据库教程【实战】

mysqli_connect() 连不上,错误提示 Connection refused 怎么办

绝大多数连不上不是代码写错,而是 MySQL 服务根本没在跑,或者端口被防火墙拦了。先确认本地 MySQL 是否运行:sudo systemctl status mysqllinux)或打开「服务」里找 mysqlwindows)。默认端口是 3306,如果改过,mysqli_connect() 的第四个参数必须显式传进去,不能只靠默认值。

常见错误现象:mysqli_connect(): (HY000/2002): Connection refused —— 这基本等于“压根没连到 MySQL 进程”。别急着查用户名密码,先 ping 不通、telnet 不通,就不用往下试了。

  • 检查 MySQL 是否监听 127.0.0.1:看配置文件 /etc/mysql/mysql.conf.d/mysqld.cnfbind-address 是不是 127.0.0.10.0.0.0,不是的话连本地都会被拒
  • 远程连接?确保用户授权用了 'user'@'%' 而非 'user'@'localhost',后者在某些系统下走 socket 而非 TCP,mysqli_connect() 强制走 TCP 就会失败
  • php 和 MySQL 版本差异大(比如 PHP 8.2 + MySQL 8.0+),默认认证插件可能是 caching_sha2_password,老 mysqli 扩展不认,得在 MySQL 里执行:ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_pass';

mysqli 面向对象方式还是过程式?选哪个更稳

两者底层完全一样,没性能差别,但面向对象写法能避免变量污染、更容易做封装。过程式写法里所有函数都依赖上一步返回的 $conn 资源,一旦漏判 mysqli_connect() 返回 false,后面 mysqli_query($conn, ...) 直接报 Warning: mysqli_query(): invalid mysqli Object

推荐无脑用面向对象,出错时异常明确,且 mysqli 类本身支持 set_charset()real_escape_string() 等方法链式调用:

$conn = new mysqli($host, $user, $pass, $db, $port); if ($conn->connect_error) {     die('连接失败:' . $conn->connect_error); } $conn->set_charset('utf8mb4');
  • 过程式必须每次手动检查 mysqli_connect() 返回值,漏一次就崩
  • 面向对象方式下,$conn->query() 失败直接返回 false,不会静默吞错;而过程式 mysqli_query() 在开启 mysqli.report 之前,默认也不报错
  • 如果项目已用 pdo,别为了“统一”硬切 mysqli —— 混用反而增加维护成本

mysqli_real_escape_string() 还安全吗?为什么总提醒用预处理

它没被废弃,但仅限于“字符串拼接 SQL”这种旧写法下兜底。只要中间经过任何变量拼接,比如 "select * FROM users WHERE name = '" . mysqli_real_escape_string($conn, $_GET['name']) . "'",就存在绕过风险:比如 MySQL 设置了 sql_mode=NO_BACKSLASH_ESCAPES,或客户端编码与连接层不一致,real_escape_string() 就可能失效。

真正防注入只有两条路:预处理(prepared statement)或严格白名单校验。预处理把 SQL 结构和数据彻底分离,MySQL 服务端自己解析参数,根本不会当 SQL 执行。

  • 预处理不是“更麻烦”,而是更少出错:用 $stmt = $conn->prepare("SELECT * FROM t WHERE id = ?"),然后 $stmt->bind_param("i", $id),类型 "i""s" 写错才真会翻车
  • mysqli_real_escape_string() 必须传入有效的 $conn 对象,如果连接已断开还调用,会警告并返回空字符串,结果查不到数据还找不到原因
  • 对非字符串字段(如数字 ID、时间戳),别用 escape,直接类型转换更干净:$id = (int)$_GET['id']

连接池、长连接、mysqli_pconnect() 到底要不要用

PHP-FPM 模式下,mysqli_pconnect() 基本没意义,甚至有害。每个 worker 进程会维持自己的持久连接,连接数会指数级上涨,很快打满 MySQL 的 max_connections。官方文档也明确说:“不建议在 Web 环境中使用”。真正的连接复用靠 MySQL 自身的连接池(MySQL 8.0+)或中间件(如 ProxySQL),PHP 层只需用好短连接 + 合理超时。

关键其实是三个超时参数:连接超时(connect_timeout)、等待响应超时(read_timeout)、发送超时(write_timeout)。默认都是 60 秒,网络卡顿或查询慢时,请求就挂死在那里,拖垮整个 FPM 进程。

  • 设连接超时:$conn = mysqli_init(); mysqli_options($conn, MYSQLI_OPT_CONNECT_TIMEOUT, 5); mysqli_real_connect(...)
  • 查慢查询?加 mysqli_options($conn, MYSQLI_OPT_READ_TIMEOUT, 10),避免一个慢 SQL 卡住整个请求
  • 别信“长连接省资源”——PHP 请求生命周期短,连接建立开销远小于维护闲置连接的成本

复杂点在于:错误处理必须覆盖连接中断、查询超时、字符集不匹配这三类问题,而它们抛出的错误码完全不同,mysqli_sqlstate()mysqli_errno() 得分开判断。很多人只 catch mysqli_connect_error,结果线上偶尔 502 却查不到日志。

text=ZqhQzanResources