MySQL資料庫5.7的錯誤堆棧緩沖
什麼是錯誤緩沖堆棧呢? 舉個很簡單的例子,比如執行下面一條語句:
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 DO GET 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 DO SET @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 DO GET 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。
You May Also Like
- PHP求天數常犯的錯誤
- PHP中的錯誤處理
- 【原創】mysql 錯誤緩沖堆棧
- NDK開發——Android Studio中開發NDK遇到的錯誤問題與解決方案匯總
- Android studio 錯誤: 程序包 不存在
- 【解決】MySql 5.6 運行崩潰錯誤
- Android編譯出現com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536錯誤解決辦法
- Mysql碰到“Everyderivedtablemusthaveitsownalias”類似錯誤說明
- 使用EventBus出現java.lang.NoClassDefFoundError: android/os/PersistableBundle錯誤
- Android 使用OKHttp3請求接口401,返回Authorization Required錯誤怎麼解決