PDO - 真相和最佳实践?

12

目前我一直在使用老版本的mysql而不是PDO,我看到了很多建议要转换到PDO的理由,但也有很多不同的事实(也包括在 Stack Overflow 上),例如:

  • 声称PDO略微更快/稍微慢一点
  • PDO有助于防止 SQL 注入,但只有在使用预处理语句时才能防止
  • 还说使用预处理查询很糟糕,因为它非常慢

那么,什么才是真实情况呢?特别是,在使用PDO并且速度和安全性都非常重要时,最佳实践是什么 - 如何在保持快速查询的同时最大限度地保护自己免受 SQL 注入攻击?


2
为什么“older”要加引号?它确实比较老,而且已经被弃用了。 - Mark Byers
1
方便性。这就是所有的方便性。使用预处理语句可以节省繁琐和手动的转义部分。这是一个副作用,但几乎消除了SQL注入。你仍然会在某个时候连接动态查询,所以忽略转义和上下文不是一个选项。但是预处理语句涵盖了大多数情况。--它是否更快取决于您当前的设置和使用情况,只有分析器才能告诉您,而不是一个模因。 - mario
2
我以前有使用过 PDO::quote(),但这要看你在做什么。我认为让你理解最好的方法是了解一下预处理语句实际上是做什么的 - 它们将查询发送到数据库服务器进行解析和准备,然后当你调用 execute() 时,它们会发送用于占位符的数据并检索结果。因此,对于只运行一次的语句,这会导致更多的数据库流量,并且会稍微拖慢速度… - DaveRandom
1
...但是(一个常见的例子)对于许多使用略有不同数据的UPDATE,它可以显著加快速度,因为查询只被解析一次并且执行计划只被设计一次,唯一的变量是在执行期间使用的数据。 - DaveRandom
1
PDO::quote() 不仅转义字符串,还会将其加上引号。另一方面,mysql_real_escape_string() 只会转义字符串。建议始终使用预处理语句而不是 PDO::quote() 和 mysql_real_escape_string()。 - abhshkdz
显示剩余4条评论
2个回答

20

数据库支持

PDO 相对于 MySQL 的核心优势在于其数据库驱动程序的支持。PDO 支持许多不同的驱动程序,如 CUBRID、MS SQL Server、Firebird/Interbase、IBM、MySQL 等。

安全性

只要开发人员按照预期使用它们,两个库都提供 SQL 注入安全性。建议使用预处理语句和绑定查询。

// PDO, prepared statement
$pdo->prepare('SELECT * FROM users WHERE username = :username');
$pdo->execute(array(':username' => $_GET['username']));

// mysqli, prepared statements
$query = $mysqli->prepare('SELECT * FROM users WHERE username = ?');
$query->bind_param('s', $_GET['username']);
$query->execute();

速度

虽然PDO和MySQL都很快,但在基准测试中,MySQL表现略微更快 - 对于非预处理语句约为2.5%,对于预处理语句约为6.5%。

命名参数

就像@DaveRandom指出的那样,这是PDO具有的另一个特性,比可怕的数字绑定容易得多。

$params = array(':username' => 'test', ':email' => $mail, ':last_login' => time() - 3600);

$pdo->prepare('
SELECT * FROM users
WHERE username = :username
AND email = :email
AND last_login > :last_login');

$pdo->execute($params);

PDO vs MySQL

以下是进一步参考的链接:
MySQL vs PDO (Stackoverflow)
为什么你应该使用PDO来访问数据库(net.tutsplus.com)


1
虽然PDO和MySQL都非常快,但您是在将PDO与mysqli_*(如示例代码中所示)还是mysql_*进行比较?此外,请注意,如果需要/想要在调用execute()之前绑定值,则PDO也可以使用绑定值。同时请注意链接:http://php.net/manual/en/pdostatement.bindvalue.php - Fabrício Matté
PDO和MySQLi的另一个主要优势是能够使用命名占位符,而不必处理MySQLi的愚蠢接口,该接口要求您必须使用bind_param()/bind_result(),而不能直接传递/检索数组,导致创建明确引用数组的可怕函数和难以阅读的call_user_func_array()结构。 - DaveRandom
PDO支持许多不同的驱动程序,如CUBRID、MS SQL Server、Firebird/Interbase、IBM、MySQL等。但是由于它们的SQL语言方言不同,所以所有DDL或非平凡DML都必须考虑到这一点。因此,PDO并不是一个跨数据库的万能解决方案。 - MaxSem
谢谢Abhishek,这是一个很棒的回答!也感谢您提供了实际例子进行比较!太棒了! - Helmut

0
在大多数情况下,开发速度(编写软件所需的时间)比对性能进行微小改进更为重要。
我建议使用PDO,并将其与预处理查询一起使用。除非您是Twitter或Google,否则您极有可能甚至不会察觉到任何性能差异。

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