簡體   English   中英

MySQL:存儲過程中的事務

[英]MySQL : transaction within a stored procedure

我的存儲過程的基本結構是,

BEGIN

    .. Declare statements ..

    START TRANSACTION;

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

    COMMIT;

END

MySQL 版本: 5.1.61-0ubuntu0.11.10.1-log

當前,如果“查詢 2”失敗,則提交“查詢 1”的結果。

  • 如果任何查詢失敗,我如何回滾事務?

看看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;

只是 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

下面是一個事務示例,它將在錯誤時回滾並返回錯誤代碼。

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 ;

這是假設自動提交設置為 0。希望這會有所幫助。

[這只是其他答案中未涉及的解釋]

至少在最新版本的 MySQL 中,您的第一個查詢未提交

如果您在同一個會話下查詢它,您將看到更改,但是如果您從不同的會話查詢它,則更改不存在,它們沒有提交

這是怎么回事?

當您打開一個事務並且其中的查詢失敗時,該事務保持打開狀態,它不會提交回滾更改。

因此,請小心,任何被先前查詢(如SELECT ... FOR SHARE/UPDATEUPDATEINSERT或任何其他鎖定查詢)鎖定的表/行都會保持鎖定狀態,直到該會話被終止(並執行回滾),或直到后續查詢顯式 ( COMMIT ) 或隱式提交它,從而使部分更改永久化(這可能在數小時后發生,而事務處於等待狀態)。

這就是為什么該解決方案涉及聲明處理程序以在發生錯誤時立即ROLLBACK


額外的

在處理程序中,您還可以使用RESIGNAL重新引發錯誤,否則存儲過程將執行“成功”

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM