作者:王佳怡1995 | 来源:互联网 | 2017-05-12 16:11
什么是错误缓冲堆栈呢?举个很简单的例子,比如执行下面一条语句:mysql>INSERTINTOt_datetimeVALUES(2,4,5);ERROR1292(22007):Incorrectdatetimevalue:4forcolumnlog_timeatrow1上面1292这个
什么是错误缓冲堆栈呢? 举个很简单的例子,比如执行下面一条语句:
mysql>INSERTINTOt_datetimeVALUES(2,'4','5');
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里,重置的条件更加宽松。以下举例子来说明。
示例表结构如下,
CREATETABLE`t_datetime`(
`id`int(11)NOTNULL,
`log_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,
`end_time`datetimeNOTNULL,
PRIMARYKEY(`id`)
)ENGINE=InnoDBDEFAULTCHARSET=utf8;
用来记录错误数据的日志表。
CREATETABLEtb_log(errornoint,errortextTEXT,error_timestampDATETIME);
在MySQL5.6环境下,我要这样写一段繁杂的代码来获取错误信息。
DELIMITER$$
USE`new_feature`$$
DROPPROCEDUREIFEXISTS`sp_do_insert`$$
CREATEDEFINER=`root`@`localhost`PROCEDURE`sp_do_insert`(
INf_idINT,
INf_log_timeVARCHAR(255),
INf_end_timeVARCHAR(255)
)
BEGIN
DECLAREdone1TINYINTDEFAULT0;--保存是否发生异常的布尔值。
DECLAREiTINYINTDEFAULT1;
DECLAREv_errcountINTDEFAULT0;--获取一次错误数据条数
DECLAREv_errnoINTDEFAULT0;--获取错误代码
DECLAREv_msgTEXT;--获取错误详细信息
DECLARECONTINUEHANDLERFORSQLEXCEPTION--定义一个异常处理块
BEGIN
SETdone1=1;--发生异常,设置为1.
getdiagnosticsv_errcount=number;
SETv_msg='';
WHILEi<=v_errcount
DO
GETDIAGNOSTICSCONDITIONi
v_errno=MYSQL_ERRNO,v_msg=MESSAGE_TEXT;
SET@stmt=CONCAT(&#39;select&#39;,v_errno,&#39;,"&#39;,v_msg,&#39;","&#39;,NOW(),&#39;"into@errno&#39;,i,&#39;,@msg&#39;,i,&#39;,@log_timestamp&#39;,i,&#39;;&#39;);
PREPAREs1FROM@stmt;
EXECUTEs1;
SETi=i+1;
ENDWHILE;
DROPPREPAREs1;
END;
INSERTINTOt_datetime(id,log_time,end_time)VALUES(f_id,f_log_time,f_end_time);
IFdone1=1THEN--把错误数据记录到表tb_log里。
SETi=1;
WHILEi<=v_errcount
DO
SET@stmt=CONCAT(&#39;insertintotb_log&#39;);
SET@stmt=CONCAT(@stmt,&#39;select@errno&#39;,i,&#39;,@msg&#39;,i,&#39;,@log_timestamp&#39;);
PREPAREs1FROM@stmt;
EXECUTEs1;
SETi=i+1;
ENDWHILE;
DROPPREPAREs1;
ENDIF;
END$$
DELIMITER;
MySQL5.7发布后,现在可以精简我的代码了。
DELIMITER$$
USE`new_feature`$$
DROPPROCEDUREIFEXISTS`sp_do_insert`$$
CREATEDEFINER=`root`@`localhost`PROCEDURE`sp_do_insert`(
INf_idINT,
INf_log_timeVARCHAR(255),
INf_end_timeVARCHAR(255)
)
BEGIN
DECLAREiTINYINTDEFAULT1;
DECLAREv_errcountINTDEFAULT0;--获取一次错误数据条数
DECLAREv_errnoINTDEFAULT0;--获取错误代码
DECLAREv_msgTEXT;--获取错误详细信息
DECLARECONTINUEHANDLERFORSQLEXCEPTION--定义一个异常处理块
BEGIN
getstackeddiagnosticsv_errcount=number;
WHILEi<=v_errcount
DO
GETstackedDIAGNOSTICSCONDITIONi--把错误数据分别保存在变量里
v_errno=MYSQL_ERRNO,v_msg=MESSAGE_TEXT;
INSERTINTOtb_logVALUES(v_errno,v_msg,NOW());
SETi=i+1;
ENDWHILE;
END;
INSERTINTOt_datetime(id,log_time,end_time)VALUES(f_id,f_log_time,f_end_time);
END$$
DELIMITER;
现在来执行下:
mysql>callsp_do_insert(2,&#39;4&#39;,&#39;5&#39;);
QueryOK,1rowaffected(0.01sec)
来检索表tb_log的数据。
mysql>select*fromtb_log\G
***************************1.row***************************
errorno:1265
errortext:Datatruncatedforcolumn&#39;log_time&#39;atrow1
error_timestamp:2015-11-1711:53:10
***************************2.row***************************
errorno:1265
errortext:Datatruncatedforcolumn&#39;end_time&#39;atrow1
error_timestamp:2015-11-1711:53:10
***************************3.row***************************
errorno:1062
errortext:Duplicateentry&#39;2&#39;forkey&#39;PRIMARY&#39;
error_timestamp:2015-11-1711:53:10
3rowsinset(0.00sec)
总结下, 如果先用到DIAGNOSTICS AREA, 最好是在存储过程里面写代码封装SQL。
以上就是【原创】mysql 错误缓冲堆栈_MySQL的内容,更多相关内容请关注PHP中文网(www.php1.cn)!