PDO - 真实的事实和最佳实践? [关闭]
Posted
技术标签:
【中文标题】PDO - 真实的事实和最佳实践? [关闭]【英文标题】:PDO - real facts and best practice? [closed] 【发布时间】:2012-07-01 22:09:10 【问题描述】:从现在开始,我一直在使用旧的 mysql
而不是 PDO
,并且我已经看到了很多建议为什么要切换到 PDO
,但也有许多不同的事实(也在这里),例如:
PDO
稍快/稍慢
说 PDO
有助于防止 SQL 注入,但前提是您使用准备好的查询
还说使用准备好的查询很糟糕,因为它太慢了
那么,什么是真实的?尤其是使用PDO
时的最佳实践是什么?速度和安全性都很重要——如何在保持快速查询的同时最好地保护自己免受 SQL 注入?
【问题讨论】:
为什么“老”在引号里?它是旧的,也被弃用了。 方便。一切都是为了方便。使用准备好的语句可以为您节省繁琐的手动转义部分。这是一个副作用,但几乎消除了 SQL 注入。您仍然会在某些时候连接动态查询,因此忽略转义和上下文不是一种选择。但准备好的陈述涵盖了大多数情况。 -- 是否更快取决于您当前的设置和使用情况,只有分析器才能判断,而不是 meme。 我知道使用PDO::quote()
,这取决于你在做什么。我认为让您理解这一点的最佳方法是了解准备好的语句实际上 做什么 - 他们将查询发送到数据库服务器进行解析和准备,然后当您调用 execute()
他们发送数据这将用于占位符并检索结果。因此,对于只运行一次的语句,这是更多的数据库流量,它会(非常非常轻微地)减慢速度......
...但是(一个常见的例子)对于许多使用略有不同数据的UPDATE
s,它可以大大加快速度,因为查询被解析并且执行计划只设计一次,唯一的变体是执行期间使用的数据。
PDO::quote() 不仅会转义字符串,还会引用它。另一方面, mysql_real_escape_string() 只会转义字符串。始终建议使用准备好的语句而不是 PDO::quote() 和 mysql_real_escape_string()。
【参考方案1】:
数据库支持
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);
几个链接供进一步参考MySQL vs PDO (***)Why you should be using PDO for database access (net.tutsplus.com)
【讨论】:
While both PDO and MySQL are quite fast
,您是将 PDO 与 mysqli_*
(如您的示例代码中所示)还是 mysql_*
进行比较?另请注意,PDO 也可以与binding values 一起使用,如果您需要/想要在调用execute()
之前绑定它们。
MySQLi 的 PDO 的其他主要优点是能够使用命名占位符,而不必处理您 需要到 bind_param()
/@987654332 的 MySQLi 的 STUPID 接口@ 并且您不能只传递/检索数组,从而导致创建显式引用数组的可怕函数和令人讨厌的不可读 call_user_func_array()
构造
"PDO 支持许多不同的驱动程序,例如 CUBRID、MS SQL Server、Firebird/Interbase、IBM、MySQL 等" - 是的,但由于它们的 SQL 方言不同,所有 DDL 或非平凡的 DML 都会必须考虑到这一点。所以不,PDO 不是跨数据库的灵丹妙药。
谢谢 Abhishek,这是一个很棒的答案!也感谢您提供比较的实际示例!太棒了!【参考方案2】:
在大多数情况下,开发速度(编写软件需要多长时间)比性能的微小改进更重要。
我建议使用 PDO,并将其与准备好的查询一起使用。除非您是 Twitter 或 Google,否则您几乎不可能意识到任何性能差异。
【讨论】:
以上是关于PDO - 真实的事实和最佳实践? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章