Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  ...  /  Caching of Prepared Statements and Stored Programs

10.10.3 预备语句和存储程序的缓存

对于客户端在会话期间可能执行多次的某些语句,服务器将语句转换为内部结构并缓存该结构,以便在执行时使用。缓存使服务器可以更高效地执行,因为它避免了重新转换语句的开销。转换和缓存适用于以下语句:

  • 预备语句,无论是使用 PREPARE 语句处理的 SQL 级别还是使用 mysql_stmt_prepare() C API 函数处理的二进制客户端/服务器协议。系统变量 max_prepared_stmt_count 控制服务器缓存的总语句数(跨所有会话的预备语句总数)。

  • 存储程序(存储过程和函数、触发器和事件)。在这种情况下,服务器将整个程序体转换并缓存。系统变量 stored_program_cache 表示服务器每个会话缓存的存储程序的近似数量。

服务器在每个会话基础上维护预备语句和存储程序的缓存。一个会话缓存的语句不可访问其他会话。当会话结束时,服务器丢弃该会话缓存的所有语句。

当服务器使用缓存的内部语句结构时,必须确保结构不失效。元数据更改可能会影响语句使用的对象,导致当前对象定义与内部语句结构中的定义不匹配。元数据更改发生在 DDL 语句中,如创建、删除、更改、重命名或截断表格,或者分析、优化或修复表格。表内容更改(例如使用 INSERTUPDATE)不更改元数据,也不影响 SELECT 语句。

以下是一个示例问题。假设客户端准备了以下语句:

PREPARE s1 FROM 'SELECT * FROM t1';

在内部结构中,SELECT * 展开为表中的列列表。如果使用 ALTER TABLE 修改表的列集,预备语句将失效。如果服务器在下次执行 s1 时没有检测到这种变化,预备语句将返回不正确的结果。

为了避免元数据更改对表或视图的影响,服务器检测这些更改,并在下次执行时自动重新准备语句。也就是说,服务器重新解析语句并重建内部结构。重新解析也发生在表或视图从表定义缓存中被刷新时,无论是隐式地为缓存中的新条目腾出空间,还是由于 FLUSH TABLES

类似地,如果存储程序中使用的对象发生更改,服务器将重新解析受影响的语句。

服务器还检测表达式中的元数据更改,这些表达式可能用于存储程序中的语句,例如 DECLARE CURSOR 或流控制语句,例如 IFCASERETURN

为了避免重新解析整个存储程序,服务器仅在需要时重新解析受影响的语句或表达式。

  • 例如,假设表或视图的元数据发生了变化。重新解析将发生在存储程序中的 SELECT * 语句中,该语句访问该表或视图,但不影响不访问该表或视图的 SELECT * 语句。

  • 当语句受到影响时,服务器仅在可能时部分重新解析语句。考虑以下 CASE 语句:

    CASE case_expr
      WHEN when_expr1 ...
      WHEN when_expr2 ...
      WHEN when_expr3 ...
      ...
    END CASE

    如果元数据更改仅影响 WHEN when_expr3,那么该表达式将被重新解析。case_expr 和其他 WHEN 表达式不需要重新解析。

重新解析使用原始转换为内部形式时的默认数据库和 SQL 模式。

服务器尝试重新解析最多三次。如果所有尝试失败,将发生错误。

重新解析是自动的,但它的发生程度会降低预备语句和存储程序的性能。

对于预备语句,Com_stmt_reprepare 状态变量跟踪重新准备的次数。