Para responder às suas preocupações:
MySQL> = 5.1.17 (ou> = 5.1.21 para as instruções PREPARE
e EXECUTE
) pode usar instruções preparadas no cache de consulta . Portanto, sua versão do MySQL + PHP pode usar instruções preparadas com o cache de consulta. No entanto, observe cuidadosamente as advertências para os resultados das consultas em cache na documentação do MySQL. Existem muitos tipos de consultas que não podem ser armazenadas em cache ou que são inúteis, embora estejam armazenadas em cache. Na minha experiência, o cache de consulta geralmente não é uma grande vitória. Consultas e esquemas precisam de construção especial para aproveitar ao máximo o cache. Freqüentemente, o armazenamento em cache no nível do aplicativo acaba sendo necessário de qualquer maneira a longo prazo.
A preparação nativa não faz diferença para a segurança. As instruções pseudo-preparadas ainda escaparão dos valores dos parâmetros de consulta, isso apenas será feito na biblioteca PDO com strings em vez de no servidor MySQL usando o protocolo binário. Em outras palavras, o mesmo código PDO será igualmente vulnerável (ou não vulnerável) a ataques de injeção, independentemente de sua EMULATE_PREPARES
configuração. A única diferença é onde ocorre a substituição do parâmetro - com EMULATE_PREPARES
, ela ocorre na biblioteca PDO; sem EMULATE_PREPARES
, ele ocorre no servidor MySQL.
Sem EMULATE_PREPARES
você pode obter erros de sintaxe no tempo de preparação em vez de no tempo de execução; com EMULATE_PREPARES
você só obterá erros de sintaxe em tempo de execução porque PDO não tem uma consulta para dar ao MySQL até o tempo de execução. Observe que isso afeta o código que você escreverá ! Especialmente se você estiver usando PDO::ERRMODE_EXCEPTION
!
Uma consideração adicional:
- Há um custo fixo para a
prepare()
(usando instruções preparadas nativas), portanto, a prepare();execute()
com instruções preparadas nativas pode ser um pouco mais lento do que emitir uma consulta de texto simples usando instruções preparadas emuladas. Em muitos sistemas de banco de dados, o plano de consulta para a também prepare()
é armazenado em cache e pode ser compartilhado com várias conexões, mas não acho que o MySQL faça isso. Portanto, se você não reutilizar seu objeto de instrução preparado para várias consultas, sua execução geral pode ser mais lenta.
Como recomendação final , acho que com versões anteriores do MySQL + PHP, você deve emular instruções preparadas, mas com suas versões mais recentes você deve desligar a emulação.
Depois de escrever alguns aplicativos que usam PDO, fiz uma função de conexão PDO que tem o que considero ser as melhores configurações. Você provavelmente deve usar algo assim ou ajustar suas configurações preferidas:
/**
* Return PDO handle for a MySQL connection using supplied settings
*
* Tries to do the right thing with different php and mysql versions.
*
* @param array $settings with keys: host, port, unix_socket, dbname, charset, user, pass. Some may be omitted or NULL.
* @return PDO
* @author Francis Avila
*/
function connect_PDO($settings)
{
$emulate_prepares_below_version = '5.1.17';
$dsndefaults = array_fill_keys(array('host', 'port', 'unix_socket', 'dbname', 'charset'), null);
$dsnarr = array_intersect_key($settings, $dsndefaults);
$dsnarr += $dsndefaults;
// connection options I like
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
// connection charset handling for old php versions
if ($dsnarr['charset'] and version_compare(PHP_VERSION, '5.3.6', '<')) {
$options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$dsnarr['charset'];
}
$dsnpairs = array();
foreach ($dsnarr as $k => $v) {
if ($v===null) continue;
$dsnpairs[] = "{$k}={$v}";
}
$dsn = 'mysql:'.implode(';', $dsnpairs);
$dbh = new PDO($dsn, $settings['user'], $settings['pass'], $options);
// Set prepared statement emulation depending on server version
$serverversion = $dbh->getAttribute(PDO::ATTR_SERVER_VERSION);
$emulate_prepares = (version_compare($serverversion, $emulate_prepares_below_version, '<'));
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, $emulate_prepares);
return $dbh;
}