MySQL : 저장 프로시저 내의 트랜잭션
저장 프로시저의 기본 구조는
BEGIN
.. Declare statements ..
START TRANSACTION;
.. Query 1 ..
.. Query 2 ..
.. Query 3 ..
COMMIT;
END
MySQL 버전: 5.1.61-0ubuntu0.11.10.1-log
현재 'query 2'가 실패하면 'query 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/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
언급URL : https://stackoverflow.com/questions/9974325/mysql-transaction-within-a-stored-procedure
'programing' 카테고리의 다른 글
| php - 연관 배열의 숫자 인덱스를 가져옵니다. (0) | 2023.01.15 |
|---|---|
| 서버를 다시 시작하지 않고 MySQL 쿼리 캐시 지우기 (0) | 2023.01.15 |
| 모든 열을 비교하는 MariaDB/MySQL을 제외한 다른 방법 (0) | 2023.01.15 |
| PHP에서 PDF를 편집하시겠습니까? (0) | 2023.01.15 |
| PHP에서 redoc을 사용하는 장점은 무엇입니까? (0) | 2023.01.14 |