mysqli还是PDO - 优缺点是什么?

342

在我们这里,我们在使用mysqli和PDO时进行预处理语句和事务支持之类的操作方面存在分歧。一些项目使用其中之一,而另一些项目则使用另一种方法。实际上,我们几乎没有可能转移到另一个关系型数据库管理系统。

我更喜欢使用PDO,因为它允许使用命名参数进行预处理语句,据我所知mysqli并不支持。

在我们将项目整合为只使用一种方法的时候,是否有其他优缺点可以选择其中一种作为标准?


5
这篇文章将帮助你选择使用哪种方法。如果你关心性能,这个可能会帮助你做出决定。 - ravi404
13个回答

243

我知道你可以从面向对象的角度、准备好的语句、成为标准等方面进行争论。但我知道大多数情况下,通过一个杀手级功能来说服某人更有效。因此,这里它是:

PDO的一个非常好的功能是,您可以自动将数据注入对象中进行提取。如果您不想使用ORM(因为它只是一个快速脚本),但您喜欢对象映射,那么它真的很酷:

class Student {

    public $id;
    public $first_name;
    public $last_name

    public function getFullName() {
        return $this->first_name.' '.$this->last_name
    }
}

try 
{
    $dbh = new PDO("mysql:host=$hostname;dbname=school", $username, $password)

    $stmt = $dbh->query("SELECT * FROM students");

    /* MAGIC HAPPENS HERE */

    $stmt->setFetchMode(PDO::FETCH_INTO, new Student);


    foreach($stmt as $student)
    {
        echo $student->getFullName().'<br />';
    } 

    $dbh = null;
}
catch(PDOException $e)
{
    echo $e->getMessage();
}

12
上述代码和 $mysqliResult->fetch_object("student") 有区别吗? - Andy Fleming
2
@e-satis 不,我使用PHP。公共字段违反了封装性,因此“作为最佳实践”,这只是...哈哈 :) Google不使用公共字段,只使用访问器:https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Access_Control。 - OZ_
6
抱歉插话,如果您希望控制变量更改时发生的事情,则需要使用getter和setter。否则,您无法保证对象的内部状态(特别是如果其中有另一个对象)。这完全与语言无关。请放宽心,批评只会使别人处于防御状态。 - James P.
2
@monadic:同意。封装当然是在处理核心组件、复杂对象等方面的一个有效论点,但是作为记录的表示形式,否则将是可读写的关联数组,这是可以接受的。此外,它允许更容易地进行类型检查,因为记录在系统中浮动。 - Dan Lugg
15
@outis 我希望我不是少数派,但我认为答案不应该根据对新开发人员的安全性来评判。听起来很严厉,但这是事实。在SO上回答问题的目的不仅仅是提供复制和粘贴的代码,还要提供理解。回答者的工作不是确保每个安全漏洞或模式缺陷都在示例中得到覆盖,因为让我们面对现实吧,将代码复制到的应用程序与使用相同代码的其他应用程序本质上是不同的。 - Mattygabe
显示剩余10条评论

57

将一个应用程序从一个数据库移动到另一个数据库并不是很常见,但迟早你会发现自己在另一个使用不同RDBMS的项目上工作。如果你熟悉PDO,那么至少在这一点上就有一件事情需要学习。

除此之外,我认为PDO API更直观,并且它感觉更真正地面向对象。mysqli感觉像是已经被对象化的过程API,如果你知道我的意思的话。简而言之,我发现使用PDO更容易,但这当然是主观的。


25

我开始使用PDO,因为我认为它的语句支持更好。我正在使用类似ActiveRecord的数据访问层,用起来比较容易实现动态生成语句。MySQLi的参数绑定必须在单个函数/方法调用中完成,所以如果你直到运行时才知道要绑定多少个参数,那么你就不得不使用call_user_func_array()(我相信这就是正确的函数名)用于选择查询。同时忘掉简单的动态结果绑定。

最重要的是,我喜欢PDO,因为它提供了一个非常合理的抽象级别。它易于在完全抽象化的系统中使用,您不想编写SQL,但它也使得使用更优化、更纯净的查询类型系统变得容易,或是混合使用两者。


2
结果绑定与动态生成的查询是可能的,我们在应用程序中这样做。然而,这是一个巨大的痛苦。 - Pim Jager

17

PDO是标准,大多数开发人员都会期望使用。mysqli本质上是一个为特定问题量身定制的解决方案,但它具有其他基于DBMS的库的所有问题。PDO是所有艰苦工作和聪明思考的归宿。


15

需要记住的另一件事是:目前(PHP 5.2),PDO库存在许多错误。它充满了奇怪的错误。例如:在将PDOStatement存储在变量中之前,应该unset()变量以避免大量的错误。这些问题中的大部分已经在PHP 5.3中得到解决,并将在2009年早期发布PHP 5.3,但该版本可能仍然有许多其他错误。如果您想要一个稳定的版本,则应专注于使用PHP 6.1的PDO,如果您想帮助社区,则应使用PHP 5.3的PDO。


2
我认为PDO所提供的收益值得理解和克服其缺陷。PHP本身充满了非常令人恼火的错误,有些我们甚至无法有效地解决,但它提供了许多好处,使我们使用它而不是其他选项。 - Brian Warshaw
11
嗯,奇怪,我从未遇到过使用PDO时出现的任何错误。而且我经常使用它。 - NikiC
Mysqli 也有 bug。所有软件都有 bug。 - Bill Karwin

10

PDO值得注意的优点之一是它的PDO::quote()方法会自动添加引号,而mysqli::real_escape_string()及其类似方法则不会:

PDO::quote()方法会在输入字符串周围加上引号(如果需要),并使用适合底层驱动程序的引号样式转义输入字符串中的特殊字符。


8

PDO将使得如果您的站点/网络应用程序真正变得非常大,扩展变得更加容易,因为您可以每天设置主和从连接来分配数据库负载,而且PHP正在朝着将PDO作为标准移动。

PDO信息

缩放Web应用程序


6
MySQLi在执行速度方面更胜一筹,但除非您使用一个良好的MySQLi包装器,否则其处理预处理语句的功能非常糟糕。
我的代码仍然存在一些错误,但如果有人需要,这里是
简而言之,如果您想要速度优势,则选择MySQLi;如果您想要易用性,则选择PDO。

2
就速度而言,您能给出基准测试吗? - Julius F
8
Jonathen Robson做了一个不错的速度对比,网址http://jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarks。总结: insert几乎相等,select对于非预处理语句mysqli约快2.5% /预处理语句约快6.7%。考虑到性能惩罚很小,使用PDO的功能和灵活性通常超过性能损失。 - Adam
1
@Adam 感谢你链接到我的博客! - jnrbsn
@daemonfire300 这是真的,不需要进行基准测试。PDO包装了mysqli库。如果有人能证明PDO比mysqli更快,我可能会感到非常惊讶。:-D - Dyin
@jnrbsn,你同意亚当所说的吗? - Basit
@Basit 是的,我同意他说的一切。PDO 的优点绝对大于缺点。我再也不使用 MySQLi 了。 - jnrbsn

5

编辑后的答案。

在使用这两个API之后,我发现有两个阻塞级别的特性使mysqli无法与本机准备好的语句一起使用。
它们已经在两个优秀(但被低估了)回答中提到:

  1. 将值绑定到任意数量的占位符
  2. 将数据作为纯数组返回

(都在这个答案中提到)

由于某种原因,mysqli在这两个方面都失败了。
现在第二个问题(get_result)已经得到了改善,但它仅适用于mysqlnd安装,意味着您不能在脚本中依赖此函数。

然而,即使到今天,它也没有绑定值的功能。

所以,只有一个选择:PDO

所有其他原因,例如

  • 命名的占位符(这种语法糖被高估了)
  • 不同的数据库支持(实际上没有人使用它)
  • 对象获取(无用的语法糖)
  • 速度差异(没有)

都不是非常重要。

同时,这两个API也缺少一些真正重要的功能,例如

  • 标识符占位符
  • 复杂数据类型的占位符,使动态绑定更加轻松
  • 更短的应用程序代码。

因此,为了满足真实的生活需求,必须创建自己的抽象库,基于其中一个API,并手动实现解析占位符。在这种情况下,我更喜欢mysqli,因为它的抽象级别较低。


终于有人知道并不否认生活的事实了... - Volkan

5

个人而言,我使用PDO,但我认为这主要是偏好的问题。

PDO具有一些功能可帮助防止SQL注入(prepared statements),但如果您对SQL小心谨慎,您也可以使用mysqli实现。

更改到另一个数据库并不是使用PDO的主要原因。只要您不使用“特殊的SQL功能”,您就可以从一个DB切换到另一个DB。但是,一旦您使用例如“SELECT ... LIMIT 1”,您就不能转到MS-SQL,因为它是“SELECT TOP 1 ...”。所以这仍然是有问题的。


22
MySQLi有准备好的语句。 - Tower

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接