文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  MySQL 诊断区域

15.6.7.7 MySQL 诊断区域

SQL 语句会生成诊断信息,这些信息会填充诊断区域。 标准 SQL 有一个诊断区域栈,其中包含每个嵌套执行上下文的诊断区域。 标准 SQL 还支持 GET STACKED DIAGNOSTICS 语法,用于在条件处理程序执行期间引用第二个诊断区域。

以下讨论描述了 MySQL 中诊断区域的结构、MySQL 识别的信息项、语句如何清除和设置诊断区域,以及诊断区域如何推入和弹出堆栈。

诊断区域结构

诊断区域包含两种信息

  • 语句信息,例如发生的条件数或受影响的行数。

  • 条件信息,例如错误代码和消息。 如果一个语句引发多个条件,则诊断区域的这部分为每个条件都有一个条件区域。 如果一个语句没有引发任何条件,则诊断区域的这部分为空。

对于产生三个条件的语句,诊断区域包含如下所示的语句和条件信息

Statement information:
  row count
  ... other statement information items ...
Condition area list:
  Condition area 1:
    error code for condition 1
    error message for condition 1
    ... other condition information items ...
  Condition area 2:
    error code for condition 2:
    error message for condition 2
    ... other condition information items ...
  Condition area 3:
    error code for condition 3
    error message for condition 3
    ... other condition information items ...
诊断区域信息项

诊断区域包含语句和条件信息项。数值项是整数。字符项的字符集为 UTF-8。任何项都不能为 NULL。如果填充诊断区域的语句未设置语句或条件项,则其值为 0 或空字符串,具体取决于项数据类型。

诊断区域的语句信息部分包含以下项:

  • NUMBER:一个整数,指示包含信息的条件区域的数量。

  • ROW_COUNT:一个整数,指示受语句影响的行数。ROW_COUNTROW_COUNT() 函数的值相同(请参阅第 14.15 节“信息函数”)。

诊断区域的条件信息部分包含每个条件的条件区域。条件区域的编号从 1 到 NUMBER 语句条件项的值。如果 NUMBER 为 0,则不存在条件区域。

每个条件区域都包含以下列表中的项。除 MYSQL_ERRNO 是 MySQL 扩展外,所有项均为标准 SQL。这些定义适用于非信号生成的条件(即由 SIGNALRESIGNAL 语句生成的条件)。对于非信号条件,MySQL 仅填充未描述为始终为空的条件项。稍后将描述信号对条件区域的影响。

  • CLASS_ORIGIN:包含 RETURNED_SQLSTATE 值的类的字符串。如果 RETURNED_SQLSTATE 值以 SQL 标准文档 ISO 9075-2(第 24.1 节,SQLSTATE)中定义的类值开头,则 CLASS_ORIGIN'ISO 9075'。否则,CLASS_ORIGIN'MySQL'

  • SUBCLASS_ORIGIN:包含 RETURNED_SQLSTATE 值的子类的字符串。如果 CLASS_ORIGIN'ISO 9075'RETURNED_SQLSTATE'000' 结尾,则 SUBCLASS_ORIGIN'ISO 9075'。否则,SUBCLASS_ORIGIN'MySQL'

  • RETURNED_SQLSTATE:指示条件的 SQLSTATE 值的字符串。

  • MESSAGE_TEXT:指示条件的错误消息的字符串。

  • MYSQL_ERRNO:指示条件的 MySQL 错误代码的整数。

  • CONSTRAINT_CATALOGCONSTRAINT_SCHEMACONSTRAINT_NAME:指示违反约束的目录、模式和名称的字符串。它们始终为空。

  • CATALOG_NAMESCHEMA_NAMETABLE_NAMECOLUMN_NAME:指示与条件相关的目录、模式、表和列的字符串。它们始终为空。

  • CURSOR_NAME:指示游标名称的字符串。它始终为空。

有关特定错误的 RETURNED_SQLSTATEMESSAGE_TEXTMYSQL_ERRNO 值,请参阅服务器错误消息参考

如果 SIGNAL(或 RESIGNAL)语句填充诊断区域,则其 SET 子句可以为除 RETURNED_SQLSTATE 之外的任何条件信息项分配对该项数据类型合法的任何值。SIGNAL 还会设置 RETURNED_SQLSTATE 值,但不是直接在其 SET 子句中。该值来自 SIGNAL 语句的 SQLSTATE 参数。

SIGNAL 还会设置语句信息项。它将 NUMBER 设置为 1。它将错误的 ROW_COUNT 设置为 -1,否则设置为 0。

诊断区域的清除和填充方式

非诊断 SQL 语句会自动填充诊断区域,并且可以使用 SIGNALRESIGNAL 语句显式设置其内容。可以使用 GET DIAGNOSTICS 检查诊断区域以提取特定项,或者使用 SHOW WARNINGSSHOW ERRORS 查看条件或错误。

SQL 语句清除和设置诊断区域的方式如下:

  • 当服务器在解析语句后开始执行语句时,它会清除非诊断语句的诊断区域。诊断语句不会清除诊断区域。以下语句是诊断语句:

  • 如果语句引发条件,则诊断区域中属于先前语句的条件将被清除。例外情况是,由 GET DIAGNOSTICSRESIGNAL 引发的条件会添加到诊断区域中,而不会清除它。

因此,即使在开始执行时通常不会清除诊断区域的语句,如果该语句引发条件,它也会清除诊断区域。

以下示例显示了各种语句对诊断区域的影响,使用 SHOW WARNINGS 显示有关存储在那里的条件的信息。

DROP TABLE 语句清除诊断区域并在条件发生时填充它:

mysql> DROP TABLE IF EXISTS test.no_such_table;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> SHOW WARNINGS;
+-------+------+------------------------------------+
| Level | Code | Message                            |
+-------+------+------------------------------------+
| Note  | 1051 | Unknown table 'test.no_such_table' |
+-------+------+------------------------------------+
1 row in set (0.00 sec)

SET 语句生成错误,因此它清除并填充诊断区域:

mysql> SET @x = @@x;
ERROR 1193 (HY000): Unknown system variable 'x'

mysql> SHOW WARNINGS;
+-------+------+-----------------------------+
| Level | Code | Message                     |
+-------+------+-----------------------------+
| Error | 1193 | Unknown system variable 'x' |
+-------+------+-----------------------------+
1 row in set (0.00 sec)

先前的 SET 语句产生了一个条件,因此 1 是此时 GET DIAGNOSTICS 唯一有效的条件编号。以下语句使用条件编号 2,这会生成一个警告,该警告会添加到诊断区域中,而不会清除它:

mysql> GET DIAGNOSTICS CONDITION 2 @p = MESSAGE_TEXT;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+-------+------+------------------------------+
| Level | Code | Message                      |
+-------+------+------------------------------+
| Error | 1193 | Unknown system variable 'xx' |
| Error | 1753 | Invalid condition number     |
+-------+------+------------------------------+
2 rows in set (0.00 sec)

现在诊断区域中有两个条件,因此相同的 GET DIAGNOSTICS 语句会成功:

mysql> GET DIAGNOSTICS CONDITION 2 @p = MESSAGE_TEXT;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @p;
+--------------------------+
| @p                       |
+--------------------------+
| Invalid condition number |
+--------------------------+
1 row in set (0.01 sec)
诊断区域堆栈的工作原理

当发生诊断区域堆栈的压入时,第一个(当前)诊断区域变为第二个(堆叠)诊断区域,并创建一个新的当前诊断区域作为它的副本。诊断区域在以下情况下被压入和弹出堆栈:

  • 执行存储程序

    在程序执行之前发生压入,之后发生弹出。如果存储程序在处理程序执行时结束,则可能会有多个诊断区域需要弹出;这是由于没有适当的处理程序的异常或由于处理程序中的 RETURN 造成的。

    然后,弹出诊断区域中的任何警告或错误条件都会添加到当前诊断区域中,但对于触发器,只添加错误。当存储程序结束时,调用者会在其当前诊断区域中看到这些条件。

  • 在存储程序中执行条件处理程序

    当由于条件处理程序激活而发生压入时,堆叠的诊断区域是压入之前存储程序中当前的区域。新的当前诊断区域是处理程序的当前诊断区域。GET [CURRENT] DIAGNOSTICSGET STACKED DIAGNOSTICS 可在处理程序中使用,以访问当前(处理程序)和堆叠(存储程序)诊断区域的内容。最初,它们返回相同的结果,但在处理程序中执行的语句会修改当前诊断区域,根据正常规则清除和设置其内容(请参阅诊断区域的清除和填充方式)。堆叠的诊断区域不能由在处理程序中执行的语句修改,但 RESIGNAL 除外。

    如果处理程序成功执行,则当前(处理程序)诊断区域将弹出,堆叠(存储程序)诊断区域将再次变为当前诊断区域。在处理程序执行期间添加到处理程序诊断区域的条件将添加到当前诊断区域。

  • 执行 RESIGNAL

    RESIGNAL 语句传递在存储程序内的复合语句中执行条件处理程序期间可用的错误条件信息。RESIGNAL 可以在传递信息之前更改部分或全部信息,并按照第 15.6.7.4 节“RESIGNAL 语句”中的描述修改诊断堆栈。

与诊断区域相关的系统变量

某些系统变量控制或与诊断区域的某些方面相关:

  • max_error_count 控制诊断区域中条件区域的数量。如果发生的条件数量超过此值,MySQL 将静默丢弃多余条件的信息。(由 RESIGNAL 添加的条件始终会被添加,必要时会丢弃较旧的条件以腾出空间。)

  • warning_count 指示发生的条件数量。这包括错误、警告和注释。通常,NUMBERwarning_count 相同。但是,随着生成的条件数量超过 max_error_countwarning_count 的值会继续增加,而 NUMBER 仍保持在 max_error_count 的上限,因为诊断区域中没有存储其他条件。

  • error_count 指示发生的错误数量。此值包括“未找到”和异常条件,但不包括警告和注释。与 warning_count 一样,其值可以超过 max_error_count

  • 如果 sql_notes 系统变量设置为 0,则不会存储注释,也不会增加 warning_count

示例:如果 max_error_count 为 10,则诊断区域最多可以包含 10 个条件区域。假设一个语句引发了 20 个条件,其中 12 个是错误。在这种情况下,诊断区域包含前 10 个条件,NUMBER 为 10,warning_count 为 20,并且 error_count 为 12。

max_error_count 值的更改要到下次尝试修改诊断区域时才会生效。如果诊断区域包含 10 个条件区域并且 max_error_count 设置为 5,则这对诊断区域的大小或内容没有立即影响。