我在MySQL的Store Procedure中有以下代码(见下文)。当我没有将所有内容都放在事务中时,我可以将Sproc上的错误直接记录到数据库中的表中。但是,当我在整个事情中放置一个START TRANSACTION
,COMMIT
和ROLLBACK
时,我的日志记录将不再有效。我猜是因为它回滚了我的日志记录?我该如何解决这个问题?
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS condition 1
@SQLState = RETURNED_SQLSTATE, @SQLMessage = MESSAGE_TEXT;
SELECT CONCAT('Database error occurred, state - ',@SQLState, '; error msg - ', @SQLMessage) INTO @errorString;
CALL Log_Errors
(@errorString,
'MySprocName',
some_variable_1,
some_variable_2);
ROLLBACK;
END;
START TRANSACTION;
-- do some stuff
-- error happens somewhere in here
COMMIT;
答案 0 :(得分:1)
一种选择是使用MyISAM表进行日志记录。 MyISAM引擎不是事务性的。即使发出了ROLLBACK,插入到MyISAM表中的行也会保持插入状态。
将MyISAM用于日志记录表会引入一些其他限制。没有强制引用完整性(外键约束)。并且没有并发的DML操作。
答案 1 :(得分:1)
问题是陈旧的,但是对于谁需要答案,你必须在LOG之前调用ROLLBACK然后调用COMMIT:
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS condition 1
@SQLState = RETURNED_SQLSTATE, @SQLMessage = MESSAGE_TEXT;
SELECT CONCAT('Database error occurred, state - ',@SQLState, '; error msg - ', @SQLMessage) INTO @errorString;
ROLLBACK;
CALL Log_Errors
(@errorString,
'MySprocName',
some_variable_1,
some_variable_2);
COMMIT;
END;
START TRANSACTION;
-- do some stuff
-- error happens somewhere in here
COMMIT;
答案 2 :(得分:0)
退出时,只需执行SELECT
并允许调用应用程序处理这样的日志记录:
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
...
SELECT
CONCAT('Database error occurred, state - ',@SQLState, '; error msg - ', @SQLMessage) as @errorString,
'MySprocName' as proc,
some_variable_1 as var1,
some_variable_2 as var2;
ROLLBACK;
END;
START TRANSACTION;
-- do some stuff
COMMIT;
调用者PHP / Python /将捕获结果集并分析它的错误。如果发现错误,它将调用Log_Errors。这也将允许您在需要时登录文件系统。
答案 3 :(得分:0)
以下是回滚代码块的示例,该功能可以将错误记录到其他表中,而不会丢失MySQL中的异常详细信息,并在记录错误后再次抛出错误。您应该在回滚和记录部分之前(之后)进行诊断。
# CREATE PROCEDURE AND OTHER DECLARE STATEMENTS HERE
# ....
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
ROLLBACK;
SET @full_error = CONCAT('ERR:', @errno, '(', @sqlstate, '):', @text);
CALL sp_logaction(@full_error); # Some logging procedure
RESIGNAL; # Rethrow the error into the wild
END;
# PROCEDURE BODY WITH START TRANSACTION & COMMIT HERE
# .....