php - 为什么我不禁用 PDO::MYSQL_ATTR_DIRECT_QUERY?

标签 php mysql pdo prepared-statement

我偶然发现了一个(恕我直言,记录很差)事实,即默认情况下 PHP PDO 为其 MySQL 驱动程序启用了标志 MYSQL_ATTR_DIRECT_QUERY

这意味着它不是实际使用准备语句,而是模拟准备语句的行为。这意味着它将占位符客户端替换为转义值,并按原样将完整查询发送到数据库。

过去这样做是有充分理由的,因为在旧版本的 MySQL 下,准备好的语句会绕过查询缓存。但这种情况已经有一段时间了。仍有轻微的性能优势,因为它减少了从您的应用程序到数据库的往返次数,但我不确定这是否值得?

使用此方法的明显缺点是我们仍然依赖客户端转义,这通常不是一个好主意。我过去遇到过 mysqli_real_escape_string 的奇怪问题,由于某些字符集配置错误,允许无效字符进入查询。我宁愿不再发生类似的事情。

我只找到关于这个问题的半真半假和肤浅的评论(例如“是的,你可以启用它”或“它会导致“问题””)。寻找我不关闭它的真正原因?无论如何,在 MySQL/PDO 中使用实际准备好的语句是否与模拟的准备好的语句不兼容?

我问的部分原因是因为我们使用依赖于 PDO 的 PHPActiverecord。它不附带测试,我不希望它在生产中突然中断,因为关闭模拟的准备好的语句会巧妙地改变某些边缘情况或其他情况下的行为。

(作为旁注,在任何人提出之前:检查 PDO::ATTR_EMULATE_PREPARES 将不起作用,因为它实际上(完全)没有为 MySQL 驱动程序实现,您必须检查 PDO::MYSQL_ATTR_DIRECT_QUERY 代替。是的,那个花了我一段时间。)

澄清一下:我想知道是否有充分的理由关闭此行为。不是我一开始就不应该关心的原因。

最佳答案

问题基于一个无效的假设:不完全支持模拟准备。 (完全支持它们)。

事实上,MYSQL_ATTR_DIRECT_QUERY 只不过是 ATTR_EMULATE_PREPARES 的别名。

源代码中的证明:connection handlingAttribute Getter CodeAttribute Setter Code .

setter 代码是最有说服力的。即:

390        case PDO_MYSQL_ATTR_DIRECT_QUERY:
391        case PDO_ATTR_EMULATE_PREPARES:
392            ((pdo_mysql_db_handle *)dbh->driver_data)->emulate_prepare = Z_BVAL_P(val);
393            PDO_DBG_RETURN(1);

有关为什么绝对应该关闭模拟准备的更多信息,请参阅 this answer .

关于php - 为什么我不禁用 PDO::MYSQL_ATTR_DIRECT_QUERY?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18803023/

相关文章:

php - 与数据库中的多个日期和时间进行比较

mysql - 使用触发器自动增量列后不连续

php - PDO 建议精炼结果与通配符不同

php - 正则表达式有条件地用超链接替换 ​​Twitter 主题标签

php - Facebook 图形 API - OAuth token

php - 如何将youtube视频网址转换为嵌入代码以在我们的网站上显示视频?

mysql从子查询中解决外部查询

python - slqlalchemy UniqueConstraint VS 索引(唯一=真)

mysql - 为什么我的 PDO Mysql 数据库连接关闭速度很慢?

php - 对 mysql 代码何时使用 PDO 进行注入(inject)证明感到困惑