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  /  ...  /  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,除了 MYSQL_ERRNO,它是一个 MySQL 扩展。定义适用于除信号外的所有条件(即,不是由 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_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_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 添加的条件总是被添加, older 条件将被丢弃以腾出空间。)

  • warning_count 表示发生的条件数量,包括错误、警告和注意。通常,NUMBERwarning_count 是相同的。但是,当生成的条件数量超过 max_error_count 时,warning_count 的值将继续增加,而 NUMBER 将保持在 max_error_count because no additional conditions are stored in the diagnostics area.

  • 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,那么这不会立即影响诊断区域的大小或内容。