什么是错误缓冲堆栈呢? 举个很简单的例子,比如执行下面一条语句:
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('select',v_errno,',"',v_msg,'","',now(),'"into@errno',i,',@msg',i,',@log_timestamp',i,';');
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('insertintotb_log');
set@stmt=concat(@stmt,'select@errno',i,',@msg',i,',@log_timestamp');
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,'4','5');
queryok,1rowaffected(0.01sec)
来检索表tb_log的数据。
mysql>select*fromtb_log\g
***************************1.row***************************
errorno:1265
errortext:datatruncatedforcolumn'log_time'atrow1
error_timestamp:2015-11-1711:53:10
***************************2.row***************************
errorno:1265
errortext:datatruncatedforcolumn'end_time'atrow1
error_timestamp:2015-11-1711:53:10
***************************3.row***************************
errorno:1062
errortext:duplicateentry'2'forkey'primary'
error_timestamp:2015-11-1711:53:10
3rowsinset(0.00sec)
总结下, 如果先用到diagnostics area, 最好是在存储过程里面写代码封装sql。
以上就是【原创】mysql 错误缓冲堆栈_mysql的内容。