第5章:数据库管理 / 5.13. MySQL查询高速缓冲 / 5.13.1. 查询高速缓冲如何工作

本节描述查询缓存的工作原理。5.13.3节,“查询高速缓冲配置”描述了怎样控制是否使用查询缓存。

查询解析之前进行比较,因此下面的两个查询被查询缓存认为是不相同的:

SELECT * FROM tbl_name
Select * from tbl_name

查询必须是完全相同的(逐字节相同)才能够被认为是相同的。另外,同样的查询字符串由于其它原因可能认为是不同的。使用不同的数据库、不同的协议版本或者不同 默认字符集的查询被认为是不同的查询并且分别进行缓存。

从查询缓存中提取一个查询之前,MySQL检查用户对所有相关数据库和表的SELECT权限。如果没有权限,不使用缓存结果。

如果从查询缓存中返回一个查询结果,服务器把Qcache_hits状态变量的值加一,而不是Com_select变量。参见5.13.4节,“查询高速缓冲状态和维护”

如果一个表被更改了,那么使用那个表的所有缓冲查询将不再有效,并且从缓冲区中移出。这包括那些映射到改变了的表的使用MERGE表的查询。一个表可以被许多类型的语句更改,例如INSERTUPDATEDELETETRUNCATEALTER TABLEDROP TABLEDROP 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 ab FROM table_c";
   /* ...*/
mysql_stmt_prepare(stmtmy_sql_stmtstrlen(my_sql_stmt));

不被缓存。参见25.2.4节,“C API预处理语句”

·         使用TEMPORARY表。

·         不使用任何表。

·         用户有某个表的列级权限。