mysql:存储过程中的事务

q5iwbnjs  于 2021-06-23  发布在  Mysql
关注(0)|答案(4)|浏览(412)

我的存储过程的基本结构是,

BEGIN

    .. Declare statements ..

    START TRANSACTION;

        .. Query 1 ..
        .. Query 2 ..
        .. Query 3 ..

    COMMIT;

END

mysql版本:5.1.61-0ubuntu0.11.10.1-log
当前,如果“查询2”失败,则提交“查询1”的结果。
如果任何查询失败,如何回滚事务?

vaj7vani

vaj7vani1#

只是rkosegi代码的另一种选择,

BEGIN

    .. Declare statements ..

    DECLARE EXIT HANDLER FOR SQLEXCEPTION 
    BEGIN
          .. set any flags etc  eg. SET @flag = 0; ..
          ROLLBACK;
    END;

    START TRANSACTION;

        .. Query 1 ..
        .. Query 2 ..
        .. Query 3 ..

    COMMIT;
    .. eg. SET @flag = 1; ..

END
syqv5f0l

syqv5f0l2#

下面是一个事务示例,它将在出现错误时回滚并返回错误代码。

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `SP_CREATE_SERVER_USER`(
    IN P_server_id VARCHAR(100),
    IN P_db_user_pw_creds VARCHAR(32),
    IN p_premium_status_name VARCHAR(100),
    IN P_premium_status_limit INT,
    IN P_user_tag VARCHAR(255),
    IN P_first_name VARCHAR(50),
    IN P_last_name VARCHAR(50)
)
BEGIN

    DECLARE errno INT;
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
    GET CURRENT DIAGNOSTICS CONDITION 1 errno = MYSQL_ERRNO;
    SELECT errno AS MYSQL_ERROR;
    ROLLBACK;
    END;

    START TRANSACTION;

    INSERT INTO server_users(server_id, db_user_pw_creds, premium_status_name, premium_status_limit)
    VALUES(P_server_id, P_db_user_pw_creds, P_premium_status_name, P_premium_status_limit);

    INSERT INTO client_users(user_id, server_id, user_tag, first_name, last_name, lat, lng)
    VALUES(P_server_id, P_server_id, P_user_tag, P_first_name, P_last_name, 0, 0);

    COMMIT WORK;

END$$
DELIMITER ;

这是假设autocommit设置为0。希望这有帮助。

ma8fv8wu

ma8fv8wu3#

看一看http://dev.mysql.com/doc/refman/5.0/en/declare-handler.html
基本上,您声明了将调用回滚的错误处理程序

START TRANSACTION;

DECLARE EXIT HANDLER FOR SQLEXCEPTION 
    BEGIN
        ROLLBACK;
        EXIT PROCEDURE;
    END;
COMMIT;
nhhxz33t

nhhxz33t4#

这只是一个解释,其他答案中没有提到
至少在mysql的最新版本中,您的第一个查询没有提交。
如果您在同一个会话下查询它,您将看到更改,但是如果您从不同的会话中查询它,更改不在那里,它们不会被提交。
发生什么事?
当您打开一个事务,而其中的查询失败时,该事务将保持打开状态,它不会提交或回滚更改。
所以要小心,任何被前一个查询锁定的表/行 SELECT ... FOR SHARE/UPDATE , UPDATE , INSERT 或任何其他锁定查询,保持锁定,直到终止该会话(并执行回滚),或直到后续查询显式提交它( COMMIT )或者隐式地,从而使部分更改成为永久性的(这可能在事务处于等待状态的几个小时后发生)。
这就是为什么解决方案需要立即声明处理程序 ROLLBACK 当错误发生时。
额外的
在处理程序内部,还可以使用 RESIGNAL ,否则存储过程将“成功”执行

BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION 
        BEGIN
            ROLLBACK;
            RESIGNAL;
        END;

    START TRANSACTION;
        #.. Query 1 ..
        #.. Query 2 ..
        #.. Query 3 ..
    COMMIT;
END

相关问题