あなたの懸念に答えるには:
MySQL> = 5.1.17(またはPREPARE
and EXECUTE
ステートメントの場合は> = 5.1.21 )では、クエリキャッシュで準備済みステートメントを使用できます。したがって、MySQL + PHPのバージョンは、クエリキャッシュで準備されたステートメントを使用できます。ただし、MySQLのドキュメントでは、クエリ結果をキャッシュする際の注意事項に注意してください。キャッシュできないクエリや、キャッシュされても役に立たないクエリには、さまざまな種類があります。私の経験では、とにかくクエリキャッシュがそれほど大きな成功を収めることはあまりありません。クエリとスキーマは、キャッシュを最大限に活用するために特別な構成が必要です。多くの場合、長期的にはアプリケーションレベルのキャッシュが必要になります。
ネイティブの準備は、セキュリティに影響を与えません。疑似準備されたステートメントは、クエリパラメータ値をエスケープします。これは、バイナリプロトコルを使用するMySQLサーバーではなく、文字列を含むPDOライブラリで行われるだけです。言い換えれば、同じPDOコードは、EMULATE_PREPARES
設定に関係なく、インジェクション攻撃に対して同様に脆弱です(または脆弱ではありません)。唯一の違いは、パラメータの置換が行われる場所EMULATE_PREPARES
です。PDOライブラリで発生します。なしEMULATE_PREPARES
では、MySQLサーバーで発生します。
実行しないEMULATE_PREPARES
と、実行時ではなく準備時に構文エラーが発生する可能性があります。EMULATE_PREPARES
PDOは、実行時までのMySQLに与えるために、クエリを持っていないので、あなただけの実行時に構文エラーが発生します。これは、作成するコードに影響することに注意してください。特に使用している場合PDO::ERRMODE_EXCEPTION
!
追加の考慮事項:
prepare()
(ネイティブの準備済みステートメントを使用)には固定コストがあるため、prepare();execute()
ネイティブの準備済みステートメントを使用したは、エミュレートされた準備済みステートメントを使用してプレーンテキストクエリを発行するよりも少し遅い場合があります。多くのデータベースシステムでは、aのクエリプランprepare()
もキャッシュされ、複数の接続で共有される場合がありますが、MySQLがこれを行うとは思いません。したがって、準備されたステートメントオブジェクトを複数のクエリで再利用しない場合、全体的な実行が遅くなる可能性があります。
最後の推奨事項として、 MySQL + PHPの古いバージョンでは準備されたステートメントをエミュレートする必要がありますが、ごく最近のバージョンではエミュレーションをオフにする必要があります。
PDOを使用するアプリをいくつか作成した後、私はPDO接続機能を作成しました。おそらく次のようなものを使用するか、好みの設定に調整する必要があります。
/**
* 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;
}