爲了回答您的問題:
的MySQL> = 5.1.17(或> = 5.1.21爲PREPARE
和EXECUTE
語句)can use prepared statements in the query cache。所以你的MySQL + PHP版本可以使用準備好的語句和查詢緩存。但是,請仔細記錄MySQL文檔中用於緩存查詢結果的注意事項。有許多類型的查詢不能被緩存或者即使被緩存也沒有用。在我的經驗中,查詢緩存通常不是一個非常大的勝利。查詢和模式需要特殊的構造才能最大限度地利用緩存。無論如何,從長遠來看,應用程序級高速緩存通常是必需的。
本地準備對安全性沒有任何影響。僞準備語句仍然會跳過查詢參數值,它只會在PDO庫中使用字符串完成,而不是使用二進制協議在MySQL服務器上完成。換句話說,無論您的EMULATE_PREPARES
設置如何,相同的PDO代碼同樣容易受到(或不易受到)注入攻擊。唯一的區別是發生參數替換的位置 - EMULATE_PREPARES
,它出現在PDO庫中;沒有EMULATE_PREPARES
,它發生在MySQL服務器上。
沒有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;
}
老實說?只要繼續使用MySQLi。如果它已經在使用準備好的語句,PDO基本上是一個毫無意義的抽象層。 *編輯*:PDO對於您不確定哪些數據庫將進入後端的綠色領域應用程序非常有用。 – jmkeyes 2012-04-12 01:59:12
對不起,我的問題之前還不清楚。我編輯過它。該應用程序目前不使用MySQLi中的預準備語句;只是mysqli_run_query()。從我讀過的,MySQLi準備的語句也繞過了查詢緩存。 – 2012-04-12 14:13:01