복붙노트

[SQL] MySQL의 : 저장 프로 시저 내에서 트랜잭션 (transaction)

SQL

MySQL의 : 저장 프로 시저 내에서 트랜잭션 (transaction)

내 저장 프로 시저의 기본 구조이며,

BEGIN

    .. Declare statements ..

    START TRANSACTION;

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

    COMMIT;

END

'쿼리 2'실패하면 현재 '검색어 1'의 결과는 최선을 다하고 있습니다.

해결법

  1. ==============================

    1.http://dev.mysql.com/doc/refman/5.0/en/declare-handler.html에서보세요

    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;
    
  2. ==============================

    2.그냥 rkosegi에 의해 코드에 대한 대안,

    그냥 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
    
  3. ==============================

    3.다음은 오류에 롤백 및 오류 코드를 반환하는 거래의 예입니다.

    다음은 오류에 롤백 및 오류 코드를 반환하는 거래의 예입니다.

    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으로 설정된다고 가정한다. 도움이 되었기를 바랍니다.

  4. ==============================

    4.이것은 단지에 대한 설명은 다른 답변에서 해결되지 않습니다

    이것은 단지에 대한 설명은 다른 답변에서 해결되지 않습니다

    MySQL의 최신 버전에서 적어도 첫 번째 쿼리는 최선을 다하고되지 않습니다.

    같은 세션에서이를 조회 할 경우 변경 사항을 볼 수 있지만 다른 세션에서이를 조회 할 경우, 변경이, 그들이 최선을 다하고되지 않습니다.

    무슨 일이야?

    당신이 거래를 열고, 실패 내부 쿼리 트랜잭션이 열려 유지하면 커밋하거나 변경을 롤백하지 않습니다.

    그래서 조심, SHARE / UPDATE, UPDATE, INSERT 또는 기타 잠금 - 쿼리에 대한 ... 이전 쿼리 likeSELECT에 잠긴 모든 테이블 / 행은 해당 세션이 살해 될 때까지 잠금 (및 롤백을 실행), 또는 때까지 계속 후속 쿼리 따라서 (트랜잭션이 대기 상태에있는 동안, 나중에 시간이 일어날 수 있음) 부분 영구적으로 변경하기, 명시 적으로 (COMMIT) 또는 암시 적으로 커밋합니다.

    이 솔루션은 오류가 발생하는 즉시 ROLLBACK 때 선언 핸들러를 포함하는 이유의 그.

    특별한

    핸들러 내부 당신은 또한 "성공적으로"그렇지 않으면 저장 프로 시저가 실행, RESIGNAL를 사용하여 오류를 다시 올릴 수 있습니다

    BEGIN
        DECLARE EXIT HANDLER FOR SQLEXCEPTION 
            BEGIN
                ROLLBACK;
                RESIGNAL;
            END;
    
        START TRANSACTION;
            #.. Query 1 ..
            #.. Query 2 ..
            #.. Query 3 ..
        COMMIT;
    END
    
  5. from https://stackoverflow.com/questions/9974325/mysql-transaction-within-a-stored-procedure by cc-by-sa and MIT license