mysqli连接失败时应立即读取connect_error(字符串描述)和connect_errno(整型错误码),二者仅在new mysqli()后有效,分别用于调试输出和条件判断,精准定位connection refused、access denied等根源问题。

mysqli连接失败时先查connect_error和connect_errno
连接不上的第一反应不是改密码或换端口,而是立刻读取这两个属性。它们比任何日志都直接反映问题根源。
常见错误现象包括:Connection refused(端口未监听)、Access denied(凭据错误)、Unknown MySQL server host(DNS或host配置错)。
-
$conn->connect_error返回字符串描述,适合调试输出;$conn->connect_errno返回整型错误码,适合做条件判断(比如if ($conn->connect_errno === 1045)专门处理权限拒绝) - 注意:这两个属性只在构造
new mysqli()后立即有效;一旦执行过query()或prepare(),它们就不再反映连接阶段的问题 - 不要依赖
die("连接失败")这种笼统提示——它掩盖了真实错误类型,线上环境应记录$conn->connect_error到日志文件
预处理语句必须用prepare() + bind_param(),不能拼接SQL
哪怕只是查一个用户ID,也别写"SELECT * FROM users WHERE id = $id"。MySQLi的预处理不是“可选项”,是防SQL注入的强制路径。
使用场景很明确:所有含用户输入的WHERE、INSERT、UPDATE操作。
-
prepare()返回mysqli_stmt对象,后续所有操作(bind_param()、execute()、get_result())都得在这个对象上调用 -
bind_param()的第一个参数是类型字符串:"i"(整型)、"s"(字符串)、"d"(浮点)、"b"(blob),顺序和占位符?一一对应,错一位就报Number of variables doesn't match number of parameters - 执行
execute()后,如果影响行数为0,不代表出错——要检查$stmt->affected_rows而非$stmt->errno
查询结果必须显式释放mysqli_result对象
很多人以为$result = $conn->query("SELECT ...")之后,变量一出作用域就会自动释放内存。实际上不会,尤其在长生命周期脚本(如CLI任务)中容易导致内存泄漏。
性能影响明显:每执行一次query(),MySQLi会在内部缓存结果集元数据和数据块,不释放会持续占用PHP堆内存。
- 对
SELECT类查询,调用$result->free()或$result->close()(二者等价) - 对预处理语句的结果,用
$stmt->get_result()拿到mysqli_result后,同样要free();如果不用get_result()而用bind_result(),则无需手动释放结果集,但必须调用$stmt->close() - 漏掉释放不会报错,但
memory_get_usage(true)会显示持续增长——这是最常被忽略的资源管理点
持久化连接要用p:localhost前缀,且必须理解清理开销
想靠mysqli持久化连接提升性能?先确认你真的需要它。Web服务器进程复用连接的收益,往往被自动清理逻辑吃掉大半。
实际生效的唯一方式:在主机名前加p:,例如new mysqli("p:localhost", ...)。其他写法(如配置mysqli.reconnect=On)对持久化无效。
- 每次从连接池取出连接时,MySQLi会隐式调用
mysql_change_user()做状态重置:回滚事务、清临时表、解锁、重置会话变量——这步不可跳过,否则残留状态会污染后续请求 - 如果你的业务逻辑本身就在每次请求末尾做了完整清理(比如显式
ROLLBACK、DROP TEMPORARY TABLE),可以考虑编译时加MYSQLI_NO_CHANGE_USER_ON_PCONNECT关掉自动清理,但需自行确保连接“干净” - 本地开发环境基本用不到持久化——Apache的
mpm_prefork或PHP-FPM的static模式下,进程存活时间短,连接复用率极低
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











