什麼是錯誤緩衝堆疊呢? 舉個很簡單的例子,比如執行下面一條語句:mysql> insert into t_datetime values(2,'4','5');
error 1292 (22007): incorrect datetime value: '4' for column 'log_time' at row 1
上面1292這個**指示的錯誤資訊儲存在**呢? 就儲存在錯誤緩衝堆疊, 在mysql裡面叫 diagnostics area。 關於這個概念,一直在mysql5.7才得到確定的更新。
在mysql5.5之前,想要得到這塊區域的資料,就只能通過c的api來獲取,從sql層面是無法檢索到的。mysql5.5 先推出了這個概念。
在mysql5.6發布後,不但可以檢索這塊區域,而且還可以重新封裝,得到我們想要的資料。但是這塊區域依然是只能儲存一次錯誤**,很容易被重置。
在mysql5.7發布後,可以更加容易的檢索這塊區域,而且把這裡的資料放到乙個stack裡,重置的條件更加寬鬆。以下舉例子來說明。
示例表結構如下,create table `t_datetime` (
`id` int(11) not null,
`log_time` timestamp not null default current_timestamp on update current_timestamp,
`end_time` datetime not null,
primary key (`id`)
) engine=innodb default charset=utf8;
用來記錄錯誤資料的日誌表。create table tb_log (errorno int,errortext text,error_timestamp datetime);
在mysql5.6環境下,我要這樣寫一段繁雜的**來獲取錯誤資訊。delimiter $$
use `new_feature`$$
drop procedure if exists `sp_do_insert`$$
create definer=`root`@`localhost` procedure `sp_do_insert`(
in f_id int,
in f_log_time varchar(255),
in f_end_time varchar(255)
begin
declare done1 tinyint default 0; -- 儲存是否發生異常的布林值。
declare i tinyint default 1;
declare v_errcount int default 0; -- 獲取一次錯誤資料條數
declare v_errno int default 0; -- 獲取錯誤**
declare v_msg text; -- 獲取錯誤詳細資訊
declare continue handler for sqlexception -- 定義乙個異常處理塊
begin
set done1 = 1; -- 發生異常,設定為1.
get diagnostics v_errcount = number;
set v_msg = '';
while i <= v_errcount
doget diagnostics condition i
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,';');
prepare s1 from @stmt;
execute s1;
set i = i + 1;
end while;
drop prepare s1;
end;
insert into t_datetime (id,log_time,end_time) values(f_id,f_log_time,f_end_time);
if done1 = 1 then -- 把錯誤資料記錄到表tb_log裡。
set i = 1;
while i <= v_errcount
doset @stmt = concat('insert into tb_log ');
set @stmt = concat(@stmt,' select @errno',i,',@msg',i,',@log_timestamp');
prepare s1 from @stmt;
execute s1;
set i = i + 1;
end while;
drop prepare s1;
end if;
end$$
delimiter ;
mysql5.7發布後,現在可以精簡我的**了。delimiter $$
use `new_feature`$$
drop procedure if exists `sp_do_insert`$$
create definer=`root`@`localhost` procedure `sp_do_insert`(
in f_id int,
in f_log_time varchar(255),
in f_end_time varchar(255)
begin
declare i tinyint default 1;
declare v_errcount int default 0; -- 獲取一次錯誤資料條數
declare v_errno int default 0; -- 獲取錯誤**
declare v_msg text; -- 獲取錯誤詳細資訊
declare continue handler for sqlexception -- 定義乙個異常處理塊
begin
get stacked diagnostics v_errcount = number;
while i <= v_errcount
doget stacked diagnostics condition i -- 把錯誤資料分別儲存在變數裡
v_errno = mysql_errno, v_msg = message_text;
insert into tb_log values (v_errno,v_msg,now());
set i = i + 1;
end while;
end;
insert into t_datetime (id,log_time,end_time) values(f_id,f_log_time,f_end_time);
end$$
delimiter ;
現在來執行下:mysql> call sp_do_insert(2,'4','5');
query ok, 1 row affected (0.01 sec)
來檢索表tb_log的資料。mysql> select * from tb_log\g
*************************** 1. row ***************************
errorno: 1265
errortext: data truncated for column 'log_time' at row 1
error_timestamp: 2015-11-17 11:53:10
*************************** 2. row ***************************
errorno: 1265
errortext: data truncated for column 'end_time' at row 1
error_timestamp: 2015-11-17 11:53:10
*************************** 3. row ***************************
errorno: 1062
errortext: duplicate entry '2' for key 'primary'
error_timestamp: 2015-11-17 11:53:10
3 rows in set (0.00 sec)
總結下, 如果先用到diagnostics area, 最好是在儲存過程裡面寫**封裝sql。
mysql顯錯注入 MySQL注入之顯錯注入
庫 就是一堆表組成的資料集合 資料庫裡自帶的系統庫 information schema information schema裡columns表裡存著所有欄位名 information schema裡schemata表裡存著所有庫名 information schema裡tables表裡存著所有表名...
MySQL顯錯注入
updatexml xml target,xpath expr,new xml 該函式將xml標記xml target的給定片段的單個部分替換為新的xml片段new xml,然後返回更改後的xml。被替換的xml target部分與使用者提供的xpath表示式xpath expr匹配。說白了,就是用...
mysql連線失敗HikariPool錯誤
com.zaxxer.hikari.pool.hikaripool hikaripool 1 exception during pool initialization.引起程式無法啟動的問題是 com.zaxxer.hikari.pool.hikaripool 沒能成功被 spring 建立,原因是...