MySQL 在处理程序中回滚
MySQL rollback in handler
我有一个存储过程,我想在其中回滚以防出现任何问题。为此,我使用了这样的 EXIT HANDLER:
DECLARE EXIT HANDLER FOR sqlexception
begin
ROLLBACK;
end;
但是这样,当我调用这个存储过程时,如果有任何错误,存储过程会成功,我不知道实际问题是什么。我希望客户端 (php) 记录错误以便对其进行故障排除。所以我这样修改:
DECLARE EXIT HANDLER FOR sqlexception
begin
get diagnostics condition 1
@p1 = MESSAGE_TEXT;
ROLLBACK;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @p1;
end;
所以现在存储过程回滚,而不是抛出处理程序拦截的异常。这很酷,但有时 MESSAGE_TEXT 超过 128 个字符,在这种情况下我得到:
Error Code: 1648. Data too long for condition item 'MESSAGE_TEXT'
当然不能接受这个方案:
DECLARE EXIT HANDLER FOR sqlexception
begin
get diagnostics condition 1
@p1 = MESSAGE_TEXT;
ROLLBACK;
SET @p1=SUBSTRING(@p1,1,128);
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @p1;
end;
有没有办法拦截任何异常,回滚,然后把同样的异常抛给客户端?
非常感谢您的帮助
我使用这个模板,它很适合我。当遇到异常时,交易流程立即跳转到DECLARE EXIT HANDLER FOR SQLEXCEPTION
。 MySQL 引擎执行的最后一条语句是 ROLLBACK
。之后,交易流移出 tblock
通过将 错误代码 和 消息 作为记录集返回来优雅地处理异常(不向 PHP 抛出错误) ,您的 PHP 代码可以轻松操作和显示。
DELIMITER $$
CREATE PROCEDURE `ProcName`( <parameters here> )
BEGIN
START TRANSACTION;
tblock: BEGIN # start: transaction block
/* catch any exceptions, then rollback */
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
@state = RETURNED_SQLSTATE,
@rtc = MYSQL_ERRNO,
@rmg = MESSAGE_TEXT; -- MySQL 5.6 > : comment diagnostics for lower versions
ROLLBACK;
END;
/* table transactions here */
COMMIT;
END tblock; # end: transaction block
SELECT @rtc AS retcode,
@rmg AS retmsg,
'some ret value' AS retval;
END$$
DELIMITER ;
在 SQL 中,作为标准,0 表示成功,非零(通常大于零)值表示错误。你可能想遵循这样的做法并将其付诸实践。
根据 Kenney 的建议,答案是:
DECLARE EXIT HANDLER FOR sqlexception
begin
ROLLBACK;
RESIGNAL;
end;
我有一个存储过程,我想在其中回滚以防出现任何问题。为此,我使用了这样的 EXIT HANDLER:
DECLARE EXIT HANDLER FOR sqlexception
begin
ROLLBACK;
end;
但是这样,当我调用这个存储过程时,如果有任何错误,存储过程会成功,我不知道实际问题是什么。我希望客户端 (php) 记录错误以便对其进行故障排除。所以我这样修改:
DECLARE EXIT HANDLER FOR sqlexception
begin
get diagnostics condition 1
@p1 = MESSAGE_TEXT;
ROLLBACK;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @p1;
end;
所以现在存储过程回滚,而不是抛出处理程序拦截的异常。这很酷,但有时 MESSAGE_TEXT 超过 128 个字符,在这种情况下我得到:
Error Code: 1648. Data too long for condition item 'MESSAGE_TEXT'
当然不能接受这个方案:
DECLARE EXIT HANDLER FOR sqlexception
begin
get diagnostics condition 1
@p1 = MESSAGE_TEXT;
ROLLBACK;
SET @p1=SUBSTRING(@p1,1,128);
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @p1;
end;
有没有办法拦截任何异常,回滚,然后把同样的异常抛给客户端? 非常感谢您的帮助
我使用这个模板,它很适合我。当遇到异常时,交易流程立即跳转到DECLARE EXIT HANDLER FOR SQLEXCEPTION
。 MySQL 引擎执行的最后一条语句是 ROLLBACK
。之后,交易流移出 tblock
通过将 错误代码 和 消息 作为记录集返回来优雅地处理异常(不向 PHP 抛出错误) ,您的 PHP 代码可以轻松操作和显示。
DELIMITER $$
CREATE PROCEDURE `ProcName`( <parameters here> )
BEGIN
START TRANSACTION;
tblock: BEGIN # start: transaction block
/* catch any exceptions, then rollback */
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
@state = RETURNED_SQLSTATE,
@rtc = MYSQL_ERRNO,
@rmg = MESSAGE_TEXT; -- MySQL 5.6 > : comment diagnostics for lower versions
ROLLBACK;
END;
/* table transactions here */
COMMIT;
END tblock; # end: transaction block
SELECT @rtc AS retcode,
@rmg AS retmsg,
'some ret value' AS retval;
END$$
DELIMITER ;
在 SQL 中,作为标准,0 表示成功,非零(通常大于零)值表示错误。你可能想遵循这样的做法并将其付诸实践。
根据 Kenney 的建议,答案是:
DECLARE EXIT HANDLER FOR sqlexception
begin
ROLLBACK;
RESIGNAL;
end;