Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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

10.10.3 缓存预处理语句和存储程序

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

  • 预备语句,包括使用PREPARE语句或使用二进制客户端/服务器协议(使用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状态变量跟踪重新准备的次数。