【问题标题】:MySQL Stored Procedure fails to ROLLBACK on ERRORMySQL 存储过程在错误时无法回滚
【发布时间】:2021-05-25 21:17:25
【问题描述】:

如果事务中的任何语句失败,我会尝试回滚事务。

这些表是 InnoDB 并且 SELECT 'ROLLBACK' 被触发,所以我知道 ROLLBACK 也应该是。

事务没有回滚。任何想法为什么?

DELIMITER $$
DROP PROCEDURE IF EXISTS spTest;
CREATE PROCEDURE `spTest`(
    IN vUserID BIGINT,
    IN vSessionRef VARCHAR(50)
)

BEGIN
    DECLARE vUserSessionID BIGINT;
    DECLARE vUserSessionIDVersionCurr INT;
    DECLARE vUserSessionIDVersionNew INT;   
    
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        SELECT 'ROLLBACK'; /* This is returned so we know the error was triggered */
        ROLLBACK; 
    END;


    START TRANSACTION;
        SELECT UserSessionID INTO vUserSessionID FROM tblUserSessions WHERE UserID = vUserID AND SessionRef = vSessionRef AND isCurrent = 1 ORDER BY VersionStartDateTime DESC LIMIT 1;
        SELECT VersionID INTO vUserSessionIDVersionCurr FROM tblUserSessions WHERE UserID = vUserID AND SessionRef = vSessionRef AND isCurrent = 1 ORDER BY VersionStartDateTime DESC LIMIT 1;  

        DROP TABLE IF EXISTS tmpUserSessionCurr;
        CREATE TEMPORARY TABLE tmpUserSessionCurr SELECT * FROM tblUserSessions WHERE UserID = vUserID AND SessionRef = vSessionRef AND isCurrent = 1 ORDER BY VersionStartDateTime DESC LIMIT 1;
        
        /* This inserted record is not rolled back */
        INSERT INTO tblUserSessions (UserSessionID, EntityID, SessionRef, UserID, ValidUntil, CreatedOn, CreatedBy, LastUpdatedOn, LastUpdatedBy, isDeleted, isCurrent)
        SELECT vUserSessionID, EntityID, SessionRef, UserID, (now() + INTERVAL 5 MINUTE), CreatedOn, CreatedBy, NOW(), 'spUserSessionCreate', 0, 1 FROM tmpUserSessionCurr;
        
        /* Deliberately using a wrongly spelt field name in the statement below to trigger and exception in order to test the rollback*/
        SELECT VersionID INTO vUserSessionIDVersionNew FROM tblUserSessions WHERE UserID = vUserID AND SessionRef = vSessionRef AND NOW() BETWEEN VersionStartDateTime AND ValidUntil AND isCurrent = 1 ORDER BY VersionStartDateTime DESC LIMIT 1;
    
        UPDATE tblUserSessions 
        SET LastUpdatedBy = "spUserSessionCreate", isCurrent = 0, VersionEndDateTime = NOW() 
        WHERE UserSessionID = vUserSessionID AND VersionID = vUserSessionIDVersionCurr;
        
        SELECT 'UPDATED' AS vStatus, UserSessionID, VersionID, EntityID, SessionRef, UserID, CreatedOn, ValidUntil FROM tblUserSessions WHERE UserID = vUserID AND SessionRef = vSessionRef AND NOW() BETWEEN VersionStartDateTime AND ValidUntil AND isCurrent = 1 ORDER BY VersionStartDateTime DESC LIMIT 1; 
        
        /* -------------------- */
        SELECT 'COMMIT';
        COMMIT;  /* In the even of a SQL Error, this point will not be reached */
    /* -------------------- */


END
$$
DELIMITER ;

【问题讨论】:

    标签: mysql transactions


    【解决方案1】:

    我推测事务中的某些内容一定会影响回滚,因此查看了其中不需要的内容,接近末尾的 SELECT 语句和 DROP TABLE

    看起来DROP TABLE 是罪魁祸首。我将它移到(之前)事务之外并且回滚工作正常。

    【讨论】:

    • 是的,创建/更改/删除表不能在事务中;它将提交到那时所做的任何事情并在之后开始一个新事务
    • 如果您对临时表使用相同的名称,则无需删除表。临时表会在此会话中隐藏真实表。
    猜你喜欢
    • 2014-12-07
    • 2012-04-12
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-26
    相关资源
    最近更新 更多