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_COUNT具有与ROW_COUNT()函数相同的值(请参见“信息函数”)。
诊断区域的条件信息部分包含每个条件的条件区域。条件区域的编号从1到NUMBER语句条件项目的值。如果NUMBER为0,则没有条件区域。
每个条件区域包含以下列表中的项目。除之外MYSQL_ERRNO,所有项目均为标准SQL ,这是MySQL扩展。这些定义适用于不是通过信号(即,通过SIGNALor RESIGNAL语句)生成的条件。对于非信号条件,MySQL仅填充未描述为始终为空的条件项。信号对条件区域的影响将在后面描述。
CLASS_ORIGIN:包含RETURNED_SQLSTATE值的类的字符串。如果该RETURNED_SQLSTATE值以SQL标准文档ISO 9075-2(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_NAME,SCHEMA_NAME,TABLE_NAME,COLUMN_NAME:字符串指示目录,架构,表和相关的状态栏。他们总是空的。CURSOR_NAME:表示光标名称的字符串。这总是空的。
对于RETURNED_SQLSTATE,MESSAGE_TEXT以及MYSQL_ERRNO特定的错误值,请参见第B.3.1节,“服务器错误信息参考”。
如果SIGNAL(或RESIGNAL)语句填充了诊断区域,则其SET子句可以分配给任何条件信息项,但RETURNED_SQLSTATE对于项数据类型合法的任何值除外。SIGNAL也会设置RETURNED_SQLSTATE值,但不能直接在其SET子句中设置。该值来自SIGNAL语句SQLSTATE参数。
SIGNAL还设置语句信息项。它设置NUMBER为1。ROW_COUNT错误设置为-1,否则设置为0。
如何清除和填充诊断区域
非诊断SQL语句自动填充诊断区域,并且可以使用SIGNALand RESIGNAL语句显式设置其内容。可以检查诊断区域GET DIAGNOSTICS以提取特定项目,或者使用SHOW WARNINGS或SHOW ERRORS参见条件或错误。
SQL语句清除并设置诊断区域,如下所示:
服务器在解析语句后开始执行语句时,会清除非诊断语句的诊断区域。诊断声明不会清除诊断区域。这些语句是诊断性的:
GET DIAGNOSTICSSHOW ERRORSSHOW WARNINGS
- 如果一条语句提出了条件,则清除诊断区域中属于较早语句的条件。唯一的例外是,由
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 = @@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] DIAGNOSTICS并且GET STACKED DIAGNOSTICS可以在处理程序内使用,以访问当前(处理程序)和堆叠(存储程序)诊断区域的内容。最初,它们返回相同的结果,但是在处理程序中执行的语句会修改当前的诊断区域,并根据常规规则清除和设置其内容(请参阅如何清除和填充诊断区域)。不能通过处理程序中执行的语句修改堆栈的诊断区域,除外RESIGNAL。如果处理程序成功执行,则会弹出当前(处理程序)诊断区域,并且堆叠的(存储的程序)诊断区域将再次成为当前诊断区域。在处理程序执行期间添加到处理程序诊断区域的条件将添加到当前诊断区域。
执行
RESIGNAL该
RESIGNAL语句传递错误条件信息,该信息在执行条件处理程序期间在存储程序内的复合语句内可用。RESIGNAL可能会在传递某些或所有信息之前对其进行更改,如“ RESIGNAL语句”中所述修改诊断堆栈。
诊断区域相关的系统变量
某些系统变量控制或与诊断区域的某些方面有关:
max_error_count控制诊断区域中条件区域的数量。如果发生的情况更多,MySQL将静默丢弃超出条件的信息。(添加的条件RESIGNAL总是会添加的,较旧的条件会根据需要舍弃以腾出空间。)warning_count指示发生的条件数。这包括错误,警告和注释。通常,NUMBER和warning_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_count和error_count12。
更改值max_error_count直到下一次尝试修改诊断区域时才生效。如果诊断区域包含10个条件区域并将max_error_count其设置为5,则对诊断区域的大小或内容没有立即影响。
