귀하의 우려에 답하려면
MySQL> = 5.1.17 (또는 PREPARE
및 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;
}