MySQL处理程序中的回滚

时间:2016-02-06 13:28:50

标签: php mysql handler sqlexception

我有一个存储过程,我想在出现任何问题时回滚。为了做到这一点,我使用这样的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;

所以现在存储过程回滚并抛出处理程序拦截的exeption。这很酷,但有时MESSAGE_TEXT超过128个字符,在这种情况下,我得到:

  

错误代码:1648。条件项目的数据太长' 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;

有没有办法拦截任何异常,回滚然后向客户端抛出相同的异常? 非常感谢您的帮助

2 个答案:

答案 0 :(得分:3)

根据Kenney的建议,答案是:

DECLARE EXIT HANDLER FOR sqlexception 
    begin
        ROLLBACK;
        RESIGNAL;
    end;

答案 1 :(得分:1)

我使用这个模板,它适用于我。遇到异常时,事务流会立即跳转到DECLARE EXIT HANDLER FOR SQLEXCEPTION。 MySQL引擎要执行的最后一个语句是ROLLBACK。之后,交易流程移出tblock

通过将错误代码消息作为记录集(不向PHP抛出错误)来优雅地处理异常,您的PHP代码可以轻松地操作和显示。< / p>

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表示成功,非零(通常大于零)表示错误。您可能希望遵循这样的规则并将其作为一种练习。