猿问

PDOMySQL:使用PDO:ATTR_EMIATE_PRINTER是否准备?

PDOMySQL:使用PDO:ATTR_EMIATE_PRINTER是否准备?

这就是我到目前为止所读到的PDO::ATTR_EMULATE_PREPARES:

  1. PDO的准备仿真性能更好,因为MySQL的原生准备绕过了查询缓存.

  2. MySQL的本机准备在安全性方面更好(防止SQL注入).

  3. MySQL的本机准备更适合错误报告.

我不知道这些说法有多真实。在选择MySQL接口时,我最关心的是防止SQL注入。第二个问题是表现。

我的应用程序目前使用过程MySQLi(没有准备好的语句),并且相当多地使用查询缓存。它很少在单个请求中重用准备好的语句。为了获得已准备语句的命名参数和安全性,我开始迁移到PDO。

我在用MySQL 5.1.61PHP 5.3.2

我该走了吗PDO::ATTR_EMULATE_PREPARES启用还是不启用?是否有一种方法既具有查询缓存的性能,又具有准备好的语句的安全性?


烙印99
浏览 497回答 3
3回答

德玛西亚99

要回答你的担忧:的MySQL>=5.1.17(或>=5.1.21)PREPARE和EXECUTE发言)可以在查询缓存中使用准备好的语句。..因此,您的MySQL+PHP版本可以在查询缓存中使用准备好的语句。但是,请仔细注意MySQL文档中缓存查询结果的注意事项。有许多类型的查询不能被缓存,或者即使它们被缓存,也是无用的。根据我的经验,查询缓存通常不是一个很大的胜利。查询和架构需要特殊的构造才能最大限度地利用缓存。通常,从长远来看,应用程序级缓存最终是必要的。本机准备对安全性没有任何影响。伪准备语句仍将转义查询参数值,它将在PDO库中使用字符串完成,而不是在MySQL服务器上使用二进制协议完成。换句话说,相同的PDO代码将同样容易受到注入攻击(或不受攻击),而不管您的攻击是什么。EMULATE_PREPARES背景。唯一的区别是参数替换发生在什么地方EMULATE_PREPARES,它发生在PDO库中;EMULATE_PREPARES,它发生在MySQL服务器上。无EMULATE_PREPARES您可能在准备时而不是在执行时出现语法错误;EMULATE_PREPARES只有在执行时才会收到语法错误,因为PDO直到执行时才会向MySQL提供查询。请注意这会影响您将要编写的代码。!尤其是如果你用PDO::ERRMODE_EXCEPTION!另一项考虑是:有固定的成本prepare()(使用本机准备的语句),因此prepare();execute()对于本机准备的语句,可能比使用模拟准备语句发出普通文本查询要慢一些。在许多数据库系统中,prepare()也是缓存的,并且可以与多个连接共享,但我认为MySQL不会这样做。因此,如果不将准备好的语句对象用于多个查询,则总体执行速度可能会更慢。作为最后建议,我认为在MySQL+PHP的旧版本中,您应该模拟准备好的语句,但是对于最新版本,您应该关闭模拟。在编写了一些使用PDO的应用程序之后,我制作了一个PDO连接函数,它具有我认为最好的设置。您可能应该使用类似的东西或调整到您喜欢的设置:/** &nbsp;*&nbsp;Return&nbsp;PDO&nbsp;handle&nbsp;for&nbsp;a&nbsp;MySQL&nbsp;connection&nbsp;using&nbsp;supplied&nbsp;settings &nbsp;* &nbsp;*&nbsp;Tries&nbsp;to&nbsp;do&nbsp;the&nbsp;right&nbsp;thing&nbsp;with&nbsp;different&nbsp;php&nbsp;and&nbsp;mysql&nbsp;versions. &nbsp;* &nbsp;*&nbsp;@param&nbsp;array&nbsp;$settings&nbsp;with&nbsp;keys:&nbsp;host,&nbsp;port,&nbsp;unix_socket,&nbsp;dbname,&nbsp;charset,&nbsp;user,&nbsp;pass.&nbsp;Some&nbsp;may&nbsp;be&nbsp;omitted&nbsp;or&nbsp;NULL. &nbsp;*&nbsp;@return&nbsp;PDO &nbsp;*&nbsp;@author&nbsp;Francis&nbsp;Avila &nbsp;*/function&nbsp;connect_PDO($settings){ &nbsp;&nbsp;&nbsp;&nbsp;$emulate_prepares_below_version&nbsp;=&nbsp;'5.1.17'; &nbsp;&nbsp;&nbsp;&nbsp;$dsndefaults&nbsp;=&nbsp;array_fill_keys(array('host',&nbsp;'port',&nbsp;'unix_socket',&nbsp;'dbname',&nbsp;'charset'),&nbsp;null); &nbsp;&nbsp;&nbsp;&nbsp;$dsnarr&nbsp;=&nbsp;array_intersect_key($settings,&nbsp;$dsndefaults); &nbsp;&nbsp;&nbsp;&nbsp;$dsnarr&nbsp;+=&nbsp;$dsndefaults; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;connection&nbsp;options&nbsp;I&nbsp;like &nbsp;&nbsp;&nbsp;&nbsp;$options&nbsp;=&nbsp;array( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PDO::ATTR_ERRMODE&nbsp;=>&nbsp;PDO::ERRMODE_EXCEPTION, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PDO::ATTR_DEFAULT_FETCH_MODE&nbsp;=>&nbsp;PDO::FETCH_ASSOC&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;connection&nbsp;charset&nbsp;handling&nbsp;for&nbsp;old&nbsp;php&nbsp;versions &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($dsnarr['charset']&nbsp;and&nbsp;version_compare(PHP_VERSION,&nbsp;'5.3.6',&nbsp;'<'))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$options[PDO::MYSQL_ATTR_INIT_COMMAND]&nbsp;=&nbsp;'SET&nbsp;NAMES&nbsp;'.$dsnarr['charset']; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;$dsnpairs&nbsp;=&nbsp;array(); &nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;($dsnarr&nbsp;as&nbsp;$k&nbsp;=>&nbsp;$v)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($v===null)&nbsp;continue; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$dsnpairs[]&nbsp;=&nbsp;"{$k}={$v}"; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;$dsn&nbsp;=&nbsp;'mysql:'.implode(';',&nbsp;$dsnpairs); &nbsp;&nbsp;&nbsp;&nbsp;$dbh&nbsp;=&nbsp;new&nbsp;PDO($dsn,&nbsp;$settings['user'],&nbsp;$settings['pass'],&nbsp;$options); &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Set&nbsp;prepared&nbsp;statement&nbsp;emulation&nbsp;depending&nbsp;on&nbsp;server&nbsp;version &nbsp;&nbsp;&nbsp;&nbsp;$serverversion&nbsp;=&nbsp;$dbh->getAttribute(PDO::ATTR_SERVER_VERSION); &nbsp;&nbsp;&nbsp;&nbsp;$emulate_prepares&nbsp;=&nbsp;(version_compare($serverversion,&nbsp;$emulate_prepares_below_version,&nbsp;'<')); &nbsp;&nbsp;&nbsp;&nbsp;$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,&nbsp;$emulate_prepares); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$dbh;}
随时随地看视频慕课网APP
我要回答