PHP数据库扩展对比:MySQL、MySQLi与PDO的区别及最佳实践
在PHP开发中,选择合适的数据库扩展对安全性和可维护性至关重要。传统`mysql_*`函数已被废弃且易受攻击;`mysqli`提供了面向对象接口、预处理语句及事务支持,适合单数据库场景;而`PDO`作为抽象层,支持多种数据库驱动,具备更强的跨平台移植能力。本文将深入对比三者的特性、安全性及代码实现。
核心结论:为什么不再使用 mysql 扩展
`PHP-MySQL`(即 `mysql_*` 系列函数)是 PHP 操作 MySQL 最原始的扩展。虽然代码简洁,但它存在致命缺陷:不支持参数绑定(Bind Param),极易引发 SQL 注入攻击。后续引入的 mysql_escape_string() 或 mysql_real_escape_string() 虽能缓解此问题,但会导致查询逻辑变得复杂且丑陋。由于安全性低且功能单一,该扩展已在 PHP 5.5 中被弃用,并在 PHP 7.0 中被彻底移除。
MySQLi:性能与安全的双重提升
MySQLi 的 “i” 代表 Improvement(改进)。它不仅提供了更安全的数据处理方式,还引入了事务处理(Transaction)、多语句执行(Multi Query)等功能。
相比 mysql,mysqli 支持两种编程风格:
第1步:过程式写法(Procedural Style)
入口为 mysqli_connect,动作需显式传递资源标识。注意,mysqli_query 的资源参数位于首位,而旧版 mysql_query 可选且位于末尾。
<?php
$conn = mysqli_connect('localhost', 'user', 'password', 'database');
$result = mysqli_query($conn, 'SELECT * FROM users');
$row = mysqli_fetch_row($result);
echo $row[0];
mysqli_close($conn);
?>
第2步:对象导向写法(Object Oriented Style)
通过 new mysqli() 创建实例,最后一个参数可直接指定默认数据库,无需额外调用 select_db()。
<?php
$conn = new mysqli('localhost', 'user', 'password', 'database');
$result = $conn->query('SELECT * FROM users');
$row = $result->fetch_row();
echo $row[0];
$conn->close();
?>
第3步:使用预处理语句防止 SQL 注入
mysqli 最大的进步在于支持 prepare 和 bind_param。这是防御 SQL 注入的最佳实践之一。
<?php
$mysqli = new mysqli($db_host, $db_user, $db_password, $db_name);
$sql = "INSERT INTO users (id, name, gender, location) VALUES (?, ?, ?, ?)";
$stmt = $mysqli->prepare($sql);
// 'dsss' 代表数据类型:double, string, string, string
$stmt->bind_param('dsss', $source_id, $source_name, $source_gender, $source_location);
$stmt->execute();
$stmt->close();
$mysqli->close();
?>
MySQLi 的优势与局限
- 优势:支持持久连接(减少服务器开销)、支持事务、支持面向对象编程、执行速度比 PDO 略快。
- 局限:仅支持 MySQL 数据库,无法直接切换其他数据库系统。
PDO:真正的数据库抽象层
PDO(PHP Data Objects)是一个数据库访问抽象层。它的核心价值在于兼容性:无论后端更换为 PostgreSQL、SQLite 还是 Oracle,只需修改 DSN(数据源名称)和部分配置,业务逻辑代码几乎无需更改。
第1步:安装与配置
PDO 并非所有环境默认开启。在 Ubuntu/Debian 系统中,可能需要通过 PECL 安装对应的驱动程序(如 pdo_mysql)。
$ pecl search pdo
# 查看可用的 PDO 驱动,例如 PDO_MYSQL 1.0.2 (stable)
第2步:建立连接与执行查询
通过 DSN 字符串指定数据库类型、主机名和库名。PDO 同样支持预处理和参数绑定。
<?php
$dsn = "mysql:host=$db_host;dbname=$db_name";
$dbh = new PDO($dsn, $db_user, $db_password);
// 设置异常模式,便于调试错误
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT name, location FROM users WHERE location = ? AND name = ?";
$sth = $dbh->prepare($sql);
$sth->execute(array($location, $name));
$result = $sth->fetch(PDO::FETCH_OBJ);
echo $result->name . $result->location;
$dbh = NULL; // 断开连接
?>
PDO 的核心优势
- 多数据库支持:同一套代码可运行在 MySQL、PostgreSQL、SQLite 等多种数据库中。
- 丰富的属性设置:可通过
PDO::setAttribute控制持久连接、错误返回方式(异常或警告)、字段大小写等。 - 灵活的列绑定:除了基本的 Prepare/Execute,还支持绑定单个列并指定数据类型。
进阶选择:ORM 框架的简洁性
对于现代 PHP 开发,直接使用底层扩展往往显得繁琐。借助 ORM(对象关系映射)框架如 ActiveRecord,可以将 SQL 操作转化为简单的对象方法调用,大幅降低对 SQL 语法的依赖,并自动处理不同数据库的方言差异。
插入数据的代码对比
PDO 写法:
<?php
$sql = "INSERT INTO users (id, name, gender, location) VALUES (?, ?, ?, ?)";
$sth = $dbh->prepare($sql);
$sth->execute(array(1, 'roga', 'male', 'tpe'));
?>
ActiveRecord ORM 写法:
<?php
$user = new User();
$user->id = 1;
$user->name = 'roga';
$user->gender = 'male';
$user->location = 'tpe';
$user->save();
?>
常见问题排查:Fatal error: Class 'mysqli' not found
在使用 new mysqli() 时如果遇到类找不到的错误,通常是因为扩展未启用。请按以下步骤检查:
- Windows 环境:编辑
php.ini,找到extension=php_mysqli.dll,去掉前面的分号;,重启 Web 服务器。 - Linux 环境:确保在安装 PHP 时编译了
--with-mysqli选项,或通过包管理器安装对应的 mysqli 模块。
总结
mysql 扩展因安全性问题已成为历史;mysqli 适合专注于 MySQL 项目,提供高性能和对象化接口;PDO 则是跨数据库项目的最佳选择,提供统一的抽象层。若追求极致的开发效率和代码整洁度,建议结合 ActiveRecord 等 ORM 框架使用。
以上就是PHP中关于MySQL、MySQLi和PDO区别的一些详细内容,更多关于PHP数据库扩展优化的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









