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  /  ...  /  The MySQL Diagnostics Area

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 或空字符串,取决于项数据类型。

诊断信息部分中的语句信息包含这些项:

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

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

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

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

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

  • MESSAGE_TEXT:条件的错误信息字符串。

  • MYSQL_ERRNO: 一个整数,表示 MySQL 错误代码的条件。

  • CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME: 字符串,指示违反约束的目录、模式和名称。它们总是为空。

  • CATALOG_NAME, SCHEMA_NAME, TABLE_NAME, COLUMN_NAME: 字符串,指示与条件相关的目录、模式、表和列。它们总是为空。

  • CURSOR_NAME: 一个字符串,指示游标名称。这总是为空。

对于特定的错误,见服务器错误参考中的 RETURNED_SQLSTATE, MESSAGE_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语句产生了单个条件,所以在这个点上,GET DIAGNOSTICS的唯一有效条件号是1。下一个语句使用条件号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_count 时,warning_count 的值继续增加,而 NUMBER 保持在 max_error_count 不变,因为不再存储额外的条件信息。

  • error_count 表示出现的错误数量。这包括“not found”和异常条件,但排除警告和注释。像 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,这对诊断区的大小或内容没有立即影响。