8.10.3.1 查询缓存的运行方式

Note

从 MySQL 5.7.20 开始,查询缓存已弃用,并在 MySQL 8.0 中删除。

本节描述查询高速缓存可操作时的工作方式。 第 8.10.3.3 节“查询缓存配置”,描述如何控制它是否可操作。

在解析之前,将传入的查询与查询缓存中的查询进行比较,因此以下两个查询被查询缓存视为不同:

SELECT * FROM tbl_name
Select * from tbl_name

查询必须完全相同(一个字节接一个字节),才能被视为相同。此外,由于其他原因,相同的查询字符串可能会被视为不同。使用不同数据库,不同协议版本或不同默认字符集的查询被视为不同查询,并分别进行缓存。

缓存不用于以下类型的查询:

  • 作为外部查询的子查询的查询

  • 在存储的函数,触发器或事件的主体内执行的查询

在从查询缓存中获取查询结果之前,MySQL 将检查用户是否对所有涉及的数据库和 table 具有SELECT特权。如果不是这种情况,则不使用缓存的结果。

如果从查询缓存返回查询结果,则服务器会递增Qcache_hits状态变量,而不是Com_select。参见第 8.10.3.4 节“查询缓存状态和维护”

如果 table 发生更改,则所有使用该 table 的缓存查询都将变为无效并从缓存中删除。这包括使用MERGEtableMap 到更改后的 table 的查询。可以通过许多类型的语句来更改 table,例如INSERTUPDATEDELETETRUNCATE TABLEALTER TABLEDROP TABLEDROP DATABASE

使用InnoDBtable 时,查询缓存也可在事务内工作。

对视图的SELECT查询的结果被缓存。

查询缓存适用于SELECT SQL_CALC_FOUND_ROWS ...查询,并存储随后的SELECT FOUND_ROWS()查询返回的值。即使从缓存中提取了先前的查询,FOUND_ROWS()也会返回正确的值,因为找到的行数也存储在缓存中。 SELECT FOUND_ROWS()查询本身不能被缓存。

使用二进制协议使用mysql_stmt_prepare()mysql_stmt_execute()(请参见第 27.7.7 节“ C API 准备语句”)发出的预准备语句在缓存方面受到限制。与查询缓存中的语句进行比较是基于扩展?参数标记后的语句文本。该语句仅与使用二进制协议执行的其他缓存语句进行比较。也就是说,出于查询缓存的目的,使用二进制协议发出的预备语句不同于使用文本协议发出的预备语句(请参见第 13.5 节“准备好的语句”)。

如果查询使用以下任何功能,则不能将其缓存:

在以下情况下,也不会缓存查询:

  • 它指的是用户定义的函数(UDF)或存储的函数。

  • 它指的是用户变量或本地存储的程序变量。

  • 它引用mysqlINFORMATION_SCHEMAperformance_schema数据库中的 table。

  • 它引用任何分区 table。

  • 它具有以下任何形式:

SELECT ... LOCK IN SHARE MODE
SELECT ... FOR UPDATE
SELECT ... INTO OUTFILE ...
SELECT ... INTO DUMPFILE ...
SELECT * FROM ... WHERE autoincrement_col IS NULL

不缓存最后一个形式,因为它用作获取最后一个插入 ID 值的 ODBC 解决方法。请参阅第 27 章,连接器和 API的连接器/ ODBC 部分。

使用SERIALIZABLE隔离级别的事务中的语句也无法缓存,因为它们使用LOCK IN SHARE MODE锁定。

  • 它使用TEMPORARY个 table。

  • 它不使用任何 table。

  • 它生成警告。

  • 用户对任何涉及的 table 都具有列级特权。