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;