本節描述查詢緩存的工作原理。5.13.3節,“查詢高速緩沖配置”描述了怎樣控制是否使用查詢緩存。
查詢解析之前進行比較,因此下面的兩個查詢被查詢緩存認為是不相同的:
SELECT * FROM tbl_name
Select * from tbl_name
查詢必須是完全相同的(逐字節相同)才能夠被認為是相同的。另外,同樣的查詢字符串由于其它原因可能認為是不同的。使用不同的數據庫、不同的協議版本或者不同 默認字符集的查詢被認為是不同的查詢并且分別進行緩存。
從查詢緩存中提取一個查詢之前,MySQL檢查用戶對所有相關數據庫和表的SELECT權限。如果沒有權限,不使用緩存結果。
如果從查詢緩存中返回一個查詢結果,服務器把Qcache_hits狀態變量的值加一,而不是Com_select變量。參見5.13.4節,“查詢高速緩沖狀態和維護”。
如果一個表被更改了,那么使用那個表的所有緩沖查詢將不再有效,并且從緩沖區中移出。這包括那些映射到改變了的表的使用MERGE表的查詢。一個表可以被許多類型的語句更改,例如INSERT、UPDATE、DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE。
COMMIT執行完后,被更改的事務InnoDB表不再有效。
使用InnoDB表時,查詢緩存也在事務中工作,使用該表的版本號來檢測其內容是否仍舊是當前的。
在MySQL 5.1中,視圖產生的查詢被緩存。
SELECT SQL_CALC_FOUND_ROWS ...和SELECT FOUND_ROWS() type類型的查詢使用查詢緩存。即使因創建的行數也被保存在緩沖區內,前面的查詢從緩存中提取,FOUND_ROWS()也返回正確的值。
如果一個查詢包含下面函數中的任何一個,它不會被緩存:
BENCHMARK() |
CONNECTION_ID() |
CURDATE() |
CURRENT_DATE() |
CURRENT_TIME() |
CURRENT_TIMESTAMP() |
CURTIME() |
DATABASE() |
帶一個參數的ENCRYPT() |
FOUND_ROWS() |
GET_LOCK() |
LAST_INSERT_ID() |
LOAD_FILE() |
MASTER_POS_WAIT() |
NOW() |
RAND() |
RELEASE_LOCK() |
SYSDATE() |
不帶參數的UNIX_TIMESTAMP() |
USER() |
|
在下面的這些條件下,查詢也不會被緩存:
· 引用自定義函數(UDFs)。
· 引用自定義變量。
· 引用mysql系統數據庫中的表。
· 下面方式中的任何一種:
SELECT ...IN SHARE MODE
SELECT ...FOR UPDATE
SELECT ...INTO OUTFILE ...
SELECT ...INTO DUMPFILE ...
SELECT * FROM ...WHERE autoincrement_col IS NULL
最后一種方式不能被緩存是因為它被用作為ODBC工作區來獲取最近插入的ID值。參見26.1.14.1節,“如何在ODBC中獲取AUTO_INCREMENT列的值”。
· 被作為編寫好的語句,即使沒有使用占位符。例如,下面使用的查詢:
char *my_sql_stmt = "SELECT a,b FROM table_c";
/* ...*/
mysql_stmt_prepare(stmt,my_sql_stmt,strlen(my_sql_stmt));
不被緩存。參見25.2.4節,“C API預處理語句”。
· 使用TEMPORARY表。
· 不使用任何表。
· 用戶有某個表的列級權限。