Mysql
 sql >> база данни >  >> RDS >> Mysql

PDO MySQL:Използвайте PDO::ATTR_EMULATE_PREPARES или не?

За да отговорите на вашите притеснения:

  1. MySQL>=5.1.17 (или>=5.1.21 за PREPARE и EXECUTE оператори) може да използва подготвени оператори в кеша на заявките . Така че вашата версия на MySQL+PHP може да използва подготвени изрази с кеша на заявките. Въпреки това, обърнете внимание на предупрежденията за кеширане на резултатите от заявката в документацията на MySQL. Има много видове заявки, които не могат да бъдат кеширани или които са безполезни, въпреки че са кеширани. Според моя опит кешът на заявките така или иначе често не е много голяма печалба. Заявките и схемите се нуждаят от специална конструкция, за да се използва максимално кеша. Често кеширането на ниво приложение все пак се оказва необходимо в дългосрочен план.

  2. Приготвянето на Native не прави никаква разлика за сигурността. Псевдо-подготвените оператори ще продължат да избягват стойностите на параметрите на заявката, просто ще бъде направено в PDO библиотеката с низове вместо на MySQL сървъра, използвайки двоичния протокол. С други думи, един и същ PDO код ще бъде еднакво уязвим (или не-уязвим) към атаки с инжектиране, независимо от вашия EMULATE_PREPARES настройка. Единствената разлика е къде се извършва подмяната на параметъра - с EMULATE_PREPARES , се среща в библиотеката на PDO; без EMULATE_PREPARES , възниква на MySQL сървъра.

  3. Без EMULATE_PREPARES може да получите синтактични грешки по време на подготовка, а не по време на изпълнение; с EMULATE_PREPARES ще получите синтактични грешки само по време на изпълнение, защото PDO няма заявка, която да даде на MySQL до момента на изпълнение. Обърнете внимание, че това засяга кода, който ще напишете ! Особено ако използвате PDO::ERRMODE_EXCEPTION !

Допълнително съображение:

  • Има фиксирана цена за prepare() (използвайки собствени подготвени оператори), така че prepare();execute() с естествени подготвени оператори може да бъде малко по-бавно от издаването на обикновена текстова заявка с помощта на емулирани подготвени оператори. В много системи за бази данни планът на заявката за 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;
}


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mySQL ::вмъкване в таблица, данни от друга таблица?

  2. Предоставяне на MySQL разрешения за таблица и колона

  3. Как да добавите колона за автоматично увеличение в съществуваща таблица в MySQL

  4. PyMySQL не може да се свърже с MySQL на localhost

  5. ADDDATE() Примери – MySQL