SQL

[MySQL] 10. Transaction

찰리-누나 2022. 12. 27.

 

 

 

 


Transaction

 

 

Transaction(트랜잭션) 이란, 데이터베이스의 상태를 바꾸기 위해 수행하는 작업의 단위를 뜻한다. 따라서 쿼리 명령어들은 각각 하나의 트랜잭션이라고 할 수 있다. 트랜잭션 문법은 DB의 내용을 직접적으로 수정하는 여러 쿼리문을 실행할 때, 최소 하나라도 에러가 발생하는 경우 전체 쿼리문을 취소할 수 있도록 도와준다. 문법과 수행 로직은 아래와 같다.

START TRANSACTION; -- 트랜잭션(한개의 작업)을 시작한다.
	쿼리 내용
COMMIT; -- 문제가 없을 경우에만 모든 코드를 실행한다.
ROLLBACK; -- 만일 에러가 발생하면 트랜잭션을 실행하기 전 상태로 되돌린다.

1. START TRANSACTION을 만나면 트랜잭션(한개의 작업)을 시작한다.

2. 쿼리 내용을 실행하되, 테이블에 반영하지는 않고 '보류' 상태로 저장해둔다.

3. COMMIT; 이라는 문법이 실행되면, '보류'상태로 두었던 결과물들을 테이블에 반영한다.

4. 만일 정상적으로 처리되지 않았다면, ROLLBACK;을 통해 트랜잭션이 실행되기 전 상태로 돌아간다.

 

정보처리기사 시험에도 나왔듯 트랜잭션 기능에는 ACID라는 속성이 있다. 모든 트랜잭션은 원자성, 일관성, 고립성, 지속성을 지켜 작성되어야 한다.

 

● Atomicity(원자성) -  한 트랜잭션의 연산들은 모두 성공하거나, 모두 실패되어야 한다.

● Consistency(일관성) - 데이터베이스의 상태가 일관되어야 한다는 성질로, 트랜잭션 이전과 이후, 데이터베이스의 상태는 이전과 같이 유효해야 한다. 즉 트랜잭션은 테이블의 제약조건과 규칙을 만족해야 한다.

● Isolation(고립성) - 모든 트랜잭션은 다른 트랜잭션으로부터 독립되어야 한다. 즉, 트랜잭션 끼리는 서로 간섭해서는 안된다.

● Durability(지속성) - COMMIT된 트랜잭션은 데이터베이스에 영구적으로 기록되어야 한다. (런타임 오류나 시스템 오류가 발생하더라도, 해당 기록은 영구적이어야 한다.)


 

 

 

먼저 START TRANSACTION은 트랜잭션을 사용하기 위해 트랜잭션을 실행해 주는 문장이다. START문장이 실행되면 이후의 삽입, 수정, 삭제 쿼리문은 실행은 가능하되 테이블에 반영되지는 않는 '보류' 상태가 된다.

 

START TRANSACTION이 실행되었다.

 

START를 통해 트랜잭션을 실행했으므로, 보류시킬 INSERT문을 작성해주었다. 정상적으로 실행되었으나 아직 '보류'상태에 있으므로 테이블에는 결과가 반영되지 않았다.

INSERT문을 실행하였지만, 실제 테이블에는 반영되지 않은 모습이다.

 

 

INSERT문이 성공적으로 실행되었으므로, COMMIT; 을 실행시켜 변경된 내용을 실제 테이블에 반영해준다.

COMMIT; 문장이 실행되어야만, 트랜잭션이 보류한 작업이 테이블에 실제로 반영된다.

 

 

만일 COMMIT이 아닌 ROLLBACK을 마지막에 실행하면, 중간의 실행 성공 여부와 관계없이 보류되었던 모든 쿼리문이 '실행취소' 된다. 

성공적으로 INSERT문이 실행되었지만, COMMIT이 아닌 ROLLBACK문이 실행되었기 때문에 쿼리문들이 테이블에 반영되지 못했다.

 

 

 

 DECLARE EXIT HANDLER FOR SQLEXCEPTION

 

내가 사용하는 node.js에서 트랜잭션의 COMMIT과 ROLLBACK은 try-catch문으로 대체된다. 작업이 성공한 경우에는 try 구문을, 실패한 경우에는 catch문을 실행하도록 작성한다. 이와 비슷한 역할을 하는 SQL 코드로 DECLARE / HANDLER 문법이 있다. 이 문법은 프로시저 안에서만 가능하며, DECLARE EXIT HANDLER FOR SQLEXCEPTION 의 밑에 있는 BEGIN과 END 사이에 '에러가 발생했을 경우 실행할 문장'을 작성한다. 보통 ROLLBACK;을 사용하므로 ROLLBACK을 작성하였다.

DROP PROCEDURE IF EXISTS DB명.프로시저명; 
DELIMITER $$ 
CREATE PROCEDURE DB명.프로시저명() 
BEGIN 

  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN 
  	-- 아래에 있는 START TRANSACTION 안에서 에러가 나면
	-- 이곳에 있는 문장을 실행한다.  
    ROLLBACK;
  END;
  
  
  START TRANSACTION;
      -- 만일 이곳에서 에러가 일어나면
      -- 위에 있는 DECLARE EXIT HANDLER FOR SQLEXCEPTION의
      -- ROLLBACK;을 실행한다.
      INSERT INTO ....
      DELETE ....
  COMMIT; 
  
END$$ 
DELIMITER ; 

CALL DB명.프로시저명();

 

프로시저 내부에 작성된 START TRANSCATION 속에 에러를 발생시키는 INSERT INTO 쿼리를 작성하여 프로시저가 실행될 경우,  DECLARE EXIT HANDLER FOR SQLEXCEPTION 가 에러를 감지해 ROLLBACK;을 실행해 주도록 프로시저를 작성하였다.

 

트랜잭션에서 (이상한데이터)를 통해 에러가 발생하였으므로, ROLLBACK이 실행되어 테이블에 아무런 일도 일어나지 않았다.

댓글