当前位置:Gxlcms > mysql > 【原创】mysql错误缓冲堆栈_MySQL

【原创】mysql错误缓冲堆栈_MySQL

时间:2021-07-01 10:21:17 帮助过:23人阅读

什么是错误缓冲堆栈呢? 举个很简单的例子,比如执行下面一条语句:

  1. mysql>INSERTINTOt_datetimeVALUES(2,'4','5');
  2. ERROR1292(22007):Incorrectdatetimevalue:'4'forcolumn'log_time'atrow1

上面1292这个代码指示的错误信息保存在哪里呢? 就保存在错误缓冲堆栈, 在MySQL里面叫 DIAGNOSTICS AREA。 关于这个概念,一直在MySQL5.7才得到确定的更新。

在MySQL5.5之前,想要得到这块区域的数据,就只能通过C的API来获取,从SQL层面是无法检索到的。MySQL5.5 先推出了这个概念。

在MySQL5.6发布后,不但可以检索这块区域,而且还可以重新封装,得到我们想要的数据。但是这块区域依然是只能保存一次错误代码,很容易被重置。

在MySQL5.7发布后,可以更加容易的检索这块区域,而且把这里的数据放到一个STACK里,重置的条件更加宽松。以下举例子来说明。

示例表结构如下,

  1. CREATETABLE`t_datetime`(
  2. `id`int(11)NOTNULL,
  3. `log_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,
  4. `end_time`datetimeNOTNULL,
  5. PRIMARYKEY(`id`)
  6. )ENGINE=InnoDBDEFAULTCHARSET=utf8;

用来记录错误数据的日志表。

  1. CREATETABLEtb_log(errornoint,errortextTEXT,error_timestampDATETIME);

在MySQL5.6环境下,我要这样写一段繁杂的代码来获取错误信息。

  1. DELIMITER$$
  2. USE`new_feature`$$
  3. DROPPROCEDUREIFEXISTS`sp_do_insert`$$
  4. CREATEDEFINER=`root`@`localhost`PROCEDURE`sp_do_insert`(
  5. INf_idINT,
  6. INf_log_timeVARCHAR(255),
  7. INf_end_timeVARCHAR(255)
  8. )
  9. BEGIN
  10. DECLAREdone1TINYINTDEFAULT0;--保存是否发生异常的布尔值。
  11. DECLAREiTINYINTDEFAULT1;
  12. DECLAREv_errcountINTDEFAULT0;--获取一次错误数据条数
  13. DECLAREv_errnoINTDEFAULT0;--获取错误代码
  14. DECLAREv_msgTEXT;--获取错误详细信息
  15. DECLARECONTINUEHANDLERFORSQLEXCEPTION--定义一个异常处理块
  16. BEGIN
  17. SETdone1=1;--发生异常,设置为1.
  18. getdiagnosticsv_errcount=number;
  19. SETv_msg='';
  20. WHILEi<=v_errcount
  21. DO
  22. GETDIAGNOSTICSCONDITIONi
  23. v_errno=MYSQL_ERRNO,v_msg=MESSAGE_TEXT;
  24. SET@stmt=CONCAT('select',v_errno,',"',v_msg,'","',NOW(),'"into@errno',i,',@msg',i,',@log_timestamp',i,';');
  25. PREPAREs1FROM@stmt;
  26. EXECUTEs1;
  27. SETi=i+1;
  28. ENDWHILE;
  29. DROPPREPAREs1;
  30. END;
  31. INSERTINTOt_datetime(id,log_time,end_time)VALUES(f_id,f_log_time,f_end_time);
  32. IFdone1=1THEN--把错误数据记录到表tb_log里。
  33. SETi=1;
  34. WHILEi<=v_errcount
  35. DO
  36. SET@stmt=CONCAT('insertintotb_log');
  37. SET@stmt=CONCAT(@stmt,'select@errno',i,',@msg',i,',@log_timestamp');
  38. PREPAREs1FROM@stmt;
  39. EXECUTEs1;
  40. SETi=i+1;
  41. ENDWHILE;
  42. DROPPREPAREs1;
  43. ENDIF;
  44. END$$
  45. DELIMITER;

MySQL5.7发布后,现在可以精简我的代码了。

  1. DELIMITER$$
  2. USE`new_feature`$$
  3. DROPPROCEDUREIFEXISTS`sp_do_insert`$$
  4. CREATEDEFINER=`root`@`localhost`PROCEDURE`sp_do_insert`(
  5. INf_idINT,
  6. INf_log_timeVARCHAR(255),
  7. INf_end_timeVARCHAR(255)
  8. )
  9. BEGIN
  10. DECLAREiTINYINTDEFAULT1;
  11. DECLAREv_errcountINTDEFAULT0;--获取一次错误数据条数
  12. DECLAREv_errnoINTDEFAULT0;--获取错误代码
  13. DECLAREv_msgTEXT;--获取错误详细信息
  14. DECLARECONTINUEHANDLERFORSQLEXCEPTION--定义一个异常处理块
  15. BEGIN
  16. getstackeddiagnosticsv_errcount=number;
  17. WHILEi<=v_errcount
  18. DO
  19. GETstackedDIAGNOSTICSCONDITIONi--把错误数据分别保存在变量里
  20. v_errno=MYSQL_ERRNO,v_msg=MESSAGE_TEXT;
  21. INSERTINTOtb_logVALUES(v_errno,v_msg,NOW());
  22. SETi=i+1;
  23. ENDWHILE;
  24. END;
  25. INSERTINTOt_datetime(id,log_time,end_time)VALUES(f_id,f_log_time,f_end_time);
  26. END$$
  27. DELIMITER;

现在来执行下:

  1. mysql>callsp_do_insert(2,'4','5');
  2. QueryOK,1rowaffected(0.01sec)

来检索表tb_log的数据。

  1. mysql>select*fromtb_log\G
  2. ***************************1.row***************************
  3. errorno:1265
  4. errortext:Datatruncatedforcolumn'log_time'atrow1
  5. error_timestamp:2015-11-1711:53:10
  6. ***************************2.row***************************
  7. errorno:1265
  8. errortext:Datatruncatedforcolumn'end_time'atrow1
  9. error_timestamp:2015-11-1711:53:10
  10. ***************************3.row***************************
  11. errorno:1062
  12. errortext:Duplicateentry'2'forkey'PRIMARY'
  13. error_timestamp:2015-11-1711:53:10
  14. 3rowsinset(0.00sec)

总结下, 如果先用到DIAGNOSTICS AREA, 最好是在存储过程里面写代码封装SQL。

以上就是【原创】mysql 错误缓冲堆栈_MySQL的内容,更多相关内容请关注PHP中文网(www.gxlcms.com)!

人气教程排行