sql >> Databáze >  >> RDS >> Mysql

PDO MySQL:Použít PDO::ATTR_EMULATE_PREPARES nebo ne?

Odpověď na vaše obavy:

  1. MySQL>=5.1.17 (nebo>=5.1.21 pro PREPARE a EXECUTE příkazy) může použít připravené příkazy v mezipaměti dotazů . Takže vaše verze MySQL+PHP může používat připravené příkazy s mezipamětí dotazů. Pozorně si však poznamenejte upozornění týkající se ukládání výsledků dotazů do mezipaměti v dokumentaci MySQL. Existuje mnoho druhů dotazů, které nelze uložit do mezipaměti nebo které jsou zbytečné, i když jsou uloženy v mezipaměti. Podle mých zkušeností není cache dotazů tak jako tak často velkou výhrou. Dotazy a schémata potřebují speciální konstrukci, aby bylo možné maximálně využít mezipaměť. Ukládání do mezipaměti na úrovni aplikace je často z dlouhodobého hlediska nezbytné.

  2. Nativní příprava nedělá žádný rozdíl pro bezpečnost. Pseudo-připravené příkazy budou stále unikat hodnotám parametrů dotazu, pouze se to provede v knihovně PDO s řetězci namísto na serveru MySQL pomocí binárního protokolu. Jinými slovy, stejný kód PDO bude stejně zranitelný (nebo nezranitelný) vůči injekčním útokům bez ohledu na váš EMULATE_PREPARES nastavení. Jediný rozdíl je v tom, kde dojde k nahrazení parametru -- pomocí EMULATE_PREPARES , vyskytuje se v knihovně PDO; bez EMULATE_PREPARES , vyskytuje se na serveru MySQL.

  3. Bez EMULATE_PREPARES můžete dostat syntaktické chyby v době přípravy spíše než v době provádění; pomocí EMULATE_PREPARES Chyby syntaxe se zobrazí pouze v době provádění, protože PDO nemá dotaz, který by mohl zadat MySQL, až do doby provádění. Všimněte si, že toto ovlivňuje kód, který budete psát ! Zejména pokud používáte PDO::ERRMODE_EXCEPTION !

Další úvaha:

  • Za prepare() je stanovena pevná cena (pomocí nativních připravených příkazů), takže prepare();execute() s nativními připravenými příkazy může být o něco pomalejší než vydávání prostého textového dotazu pomocí emulovaných připravených příkazů. Na mnoha databázových systémech plán dotazů pro prepare() je také v mezipaměti a může být sdílen s více připojeními, ale nemyslím si, že to MySQL dělá. Pokud tedy znovu nepoužijete připravený objekt příkazu pro více dotazů, může být celkové provádění pomalejší.

Jako poslední doporučení , Myslím, že se staršími verzemi MySQL+PHP byste měli emulovat připravené příkazy, ale u vašich nejnovějších verzí byste měli emulaci vypnout.

Po napsání několika aplikací, které používají PDO, jsem vytvořil funkci připojení PDO, která má podle mě nejlepší nastavení. Pravděpodobně byste měli použít něco takového nebo upravit svá preferovaná nastavení:

/**
 * 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. Najmout nebo najmout:Datový model pro proces náboru

  2. Jak odebrat databázový poštovní účet z profilu v SQL Server (T-SQL)

  3. Kolekce Oracle PL/SQL – Přidání prvků do existující tabulky

  4. PostgreSQL přízvuk + vyhledávání bez rozlišení velkých a malých písmen