mysql mysqli和PDO哪个好_mysql PHP类库选择

来源:这里教程网 时间:2026-02-28 20:40:17 作者:

直接说结论:PDO 更好,但不是因为“高级”,而是因为它更贴近现代 PHP 的设计逻辑和实际维护需求。如果你只做单数据库、小项目、不换库、不写测试,

mysqli
也能跑通;但只要涉及多环境、多数据库类型、或需要可测性、可扩展性,
PDO
的抽象层优势立刻体现出来。

为什么 PDO 的预处理默认更安全

PDO
在启用
PDO::ATTR_EMULATE_PREPARES => false
时,会把参数真正交给 MySQL 服务端做预编译,SQL 结构和数据完全分离。而
mysqli
prepare()
默认行为取决于配置,容易误以为“用了 prepare 就一定防注入”,其实如果
mysqli.reconnect=On
或连接中断后重连,某些旧版本会退化成模拟预处理,导致绕过。

PDO
的绑定写法统一:
$stmt->bindParam(':name', $name, PDO::PARAM_STR)
mysqli
要手动数参数类型:
$stmt->bind_param('s', $name)
,类型字符错一位就静默失败
批量插入时,
PDO
可复用同一
PreparedStatement
多次
execute()
mysqli
bind_param()
每次都要重绑

mysqli_real_escape_string 不能替代预处理

这是老项目里最常踩的坑:用

mysqli_real_escape_string()
拼 SQL 字符串,自以为防住了注入。但它只对字符串有效,对表名、字段名、
ORDER BY
子句、
LIMIT
偏移量等**无法转义的位置完全无效**,且在字符集不一致(如连接用
utf8mb4
,但客户端声明为
latin1
)时可能失效。

错误示例:
"SELECT * FROM user WHERE id = " . mysqli_real_escape_string($conn, $_GET['id'])
——
id
是数字,不该用字符串转义,应强制
(int)
或用预处理
正确做法:所有动态值一律走
prepare + bind
,哪怕只是
LIMIT ?, ?
mysqli
不提供对标识符(如表名)的安全插值机制,PDO 同样没有——这类内容必须白名单校验,不能靠“转义”

PDO 切换数据库几乎零成本

当项目需要从 MySQL 迁到 PostgreSQL,或测试时想用 SQLite 内存库,

PDO
只需改一行 DSN:
mysql:host=localhost;dbname=test
sqlite:/tmp/test.db
,其余
prepare
/
execute
/
fetch
代码全都不动。而
mysqli
是 MySQL 专属,函数名、错误码、事务控制方式、甚至
last_insert_id()
的行为都不同。

立即学习“PHP免费学习笔记(深入)”;

PDO
统一异常模式:
new PDO($dsn, $u, $p, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION])
,出错直接抛
PDOException
mysqli
默认是静默失败,要手动
mysqli_error()
或设
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)
才接近 PDO 行为
PDO::quote()
虽不推荐用于变量插值,但在动态生成 SQL 片段(如
IN (?)
列表)时比手写引号拼接更可靠
$pdo = new PDO('mysql:host=localhost;dbname=test', $user, $pass, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
$stmt = $pdo->prepare("SELECT id, name FROM user WHERE status = ? AND created_at > ?");
$stmt->execute(['active', '2024-01-01']);
$rows = $stmt->fetchAll();

真正容易被忽略的是:无论选

mysqli
还是
PDO
,**连接复用、长连接配置、字符集声明(
SET NAMES utf8mb4
)、以及事务边界是否显式控制**,这些对稳定性和性能的影响远大于 API 差异。别花时间争论“哪个好”,先确保你的
init_connect
或连接建立后第一句执行了正确的字符集设置。

相关推荐