Documentation Home

13.6.7.7 MySQL诊断区

SQL 语句产生填充诊断区域的诊断信息。标准 SQL 有一个诊断区域堆栈,包含每个嵌套执行上下文的诊断区域。标准 SQL 还支持GET STACKED DIAGNOSTICS在条件处理程序执行期间引用第二个诊断区域的语法。MySQL 直到 MySQL 5.7 才支持STACKED关键字。在 MySQL 5.6 中,有一个诊断区域包含来自最近写入它的语句的信息。

下面的讨论描述了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_COUNT与函数具有相同的值 ROW_COUNT()(请参阅 第 12.16 节,“信息函数”)。

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

每个条件区域都包含以下列表中的项目。所有项目都是标准 SQL,除了 MYSQL_ERRNO,它是 MySQL 扩展。这些定义适用于非信号(即SIGNALor RESIGNAL语句)生成的条件。对于非信号条件,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_ORIGINis'ISO 9075'RETURNED_SQLSTATE 以 结尾'000'SUBCLASS_ORIGIN则 is '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_SQLSTATEMESSAGE_TEXTMYSQL_ERRNO值,请参阅服务器错误消息参考

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

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

如何清除和填充诊断区域

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

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

  • 当服务器在解析语句后开始执行语句时,它会清除使用表的非诊断语句的诊断区域。诊断语句不会清除诊断区域。这些陈述是诊断性的:

  • 如果语句引发条件,诊断区域将清除属于较早语句的条件。GET DIAGNOSTICS例外情况是由和 引发的条件 RESIGNAL被添加到诊断区域而不清除它。

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

以下示例显示了各种语句对诊断区域的影响,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 = 1;
Query OK, 0 rows affected (0.00 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)
与诊断区域相关的系统变量

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

  • max_error_count控制诊断区域中条件区域的数量。如果出现比这个更多的条件,MySQL 会默默地丢弃多余条件的信息。(RESIGNAL总是添加由添加的条件,并根据需要丢弃较旧的条件以腾出空间。)

  • warning_count指示发生的条件数。这包括错误、警告和注释。通常, NUMBERwarning_count是相同的。但是,随着生成的条件数超过max_error_count, 的值 warning_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、20 warning_counterror_count12。

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

在 MySQL 5.6 之前,语句信息项不能直接使用。ROW_COUNT可以通过调用ROW_COUNT() 函数获取。由系统变量NUMBER的值近似。warning_count然而,虽然NUMBER上限为 的值max_error_count,但 warning_count不是。