Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

PDO MySQL:Gunakan PDO::ATTR_EMULATE_PREPARES atau tidak?

Untuk menjawab kekhawatiran Anda:

  1. MySQL>=5.1.17 (atau>=5.1.21 untuk PREPARE dan EXECUTE pernyataan) dapat menggunakan pernyataan yang disiapkan dalam cache kueri . Jadi versi MySQL+PHP Anda dapat menggunakan pernyataan yang disiapkan dengan cache kueri. Namun, perhatikan baik-baik peringatan untuk caching hasil kueri dalam dokumentasi MySQL. Ada banyak jenis kueri yang tidak dapat di-cache atau yang tidak berguna meskipun di-cache. Dalam pengalaman saya, cache kueri seringkali bukan merupakan kemenangan yang sangat besar. Kueri dan skema memerlukan konstruksi khusus untuk memaksimalkan penggunaan cache. Seringkali cache tingkat aplikasi tetap diperlukan dalam jangka panjang.

  2. Persiapan asli tidak membuat perbedaan untuk keamanan. Pernyataan yang disiapkan semu masih akan lolos dari nilai parameter kueri, itu hanya akan dilakukan di perpustakaan PDO dengan string, bukan di server MySQL menggunakan protokol biner. Dengan kata lain, kode PDO yang sama akan sama-sama rentan (atau tidak rentan) terhadap serangan injeksi terlepas dari EMULATE_PREPARES Anda. pengaturan. Satu-satunya perbedaan adalah di mana penggantian parameter terjadi--dengan EMULATE_PREPARES , itu terjadi di perpustakaan PDO; tanpa EMULATE_PREPARES , itu terjadi di server MySQL.

  3. Tanpa EMULATE_PREPARES anda mungkin mendapatkan kesalahan sintaks pada waktu persiapan daripada pada waktu eksekusi; dengan EMULATE_PREPARES Anda hanya akan mendapatkan kesalahan sintaks pada waktu eksekusi karena PDO tidak memiliki kueri untuk diberikan ke MySQL hingga waktu eksekusi. Perhatikan bahwa ini memengaruhi kode yang akan Anda tulis ! Terutama jika Anda menggunakan PDO::ERRMODE_EXCEPTION !

Pertimbangan tambahan:

  • Ada biaya tetap untuk prepare() (menggunakan pernyataan asli yang disiapkan), jadi prepare();execute() dengan pernyataan yang disiapkan asli mungkin sedikit lebih lambat daripada mengeluarkan kueri tekstual biasa menggunakan pernyataan yang disiapkan yang ditiru. Pada banyak sistem database, rencana kueri untuk prepare() di-cache juga dan dapat dibagikan dengan banyak koneksi, tetapi saya tidak berpikir MySQL melakukan ini. Jadi, jika Anda tidak menggunakan kembali objek pernyataan yang telah disiapkan untuk beberapa kueri, keseluruhan eksekusi Anda mungkin akan lebih lambat.

Sebagai rekomendasi akhir , saya pikir dengan versi MySQL+PHP yang lebih lama, Anda harus meniru pernyataan yang telah disiapkan, tetapi dengan versi terbaru Anda, Anda harus menonaktifkan emulasi.

Setelah menulis beberapa aplikasi yang menggunakan PDO, saya telah membuat fungsi koneksi PDO yang menurut saya adalah pengaturan terbaik. Anda mungkin harus menggunakan sesuatu seperti ini atau mengubah pengaturan pilihan Anda:

/**
 * 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. Penggunaan PDO di kelas

  2. 1114 (HY000):Meja sudah penuh

  3. Panggil ke fungsi anggota execute() pada boolean di

  4. INSERT ... PADA DUPLICATE KEY UPDATE dengan WHERE?

  5. MySQL - Cara memilih data berdasarkan panjang string