Files
2021-12-13 21:23:43 +09:00

8.1 KiB

36강. 트랜잭션

여기에서는 트랜잭션에 대해서 알아본다.

트랜잭션의 제어

START TRANSACTION
COMMIT
ROLLBACK

36강 트랜잭션

  • 데이터베이스는 트랙잭션이라는 기능을 제공한다.
  • INSERTUPDATE 명령으로 데이터를 추가, 갱신할 때도 트랜잭션 기능을 사용하지만 지금까지 특별히 의식할 필요는 없었다.
  • 이는 자동 커밋이라 불리는 기능이 동작했기 때문이다.

1. 트랜잭션

정규화에 의해 분할된 주문 테이블과 주문상품 테이블의 관계를 생각해보자.

36강 주문 테이블과 주문상품 테이블

  • 주문 테이블과 주문상품 테이블 사이에는 의존관계가 존재한다.
  • 주문 테이블에 행이 존재한다면 주문상품 테이블에는 적어도 하나의 행이 존재해야 한다.
  • 그렇지 않으면 주문한 상품이 없는데도 주문이 된 상태가 된다.
  • 보통은 하나 이상의 상품을 주문하므로 주문이 발생하면 주문 테이블과 주문상품 테이블 모두 행이 추가된다.
  • 물론 있다, 없다는 주문번호와 관련이 있으므로 '같은 주문번호로'라는 조건을 붙일 수 있다.

발주처리

  • 주문이 발생했을 때 어떻게 처리되는지 생각해보자. 간단히 말하자면 발주처리에 관한 것으로, 먼저 주문번호를 지정해야 한다.
  • 이때 기존 주문과 구분되는 주문번호를 발행하는 처리가 필요하다.
  • 자동 증가를 사용하면 자동적으로 번호가 부여되지만 그렇지 않은 경우에는 '번호 중 가장 큰 값을 SELECT 명령으로 가져와 그 값에 1을 더한다'라는 처리가 필요하다.
  • 최대값은 MAX()로 검색할 수 있으므로 MAX + 1이라 할 수도 있다.
  • 번호를 발행 받았다면 해당 번호를 키로 삼아 INSERT가 이루어진다.
  • 주문 테이블에는 INSERT 한 번, 주문상품 테이블에는 주문된 상품 수만큼 INSERT 명령이 실행된다.
  • 중요한 것은 복수의 테이블에 INSERT 되므로 실행되는 명령은 최소 두 번이라는 것이다.

발주처리

INSERT INTO 주문 VALUES(4, '2014-03-01', 1);
INSERT INTO 주문상품 VALUES(4, '0003', 1);
INSERT INTO 주문상품 VALUES(4, '0004', 2);
  • 여기서 INSERT 명령이 특정 원인으로 인해 에러가 발생한 경우를 가정해보자.
  • 트랜잭션 기능을 사용하지 않을 때는 문제없이 실행된 INSERT 명령을 실행 전으로 되돌릴 수 없으므로 따로 DELETE 명령을 실행해 지워야한다.
  • 즉, 위의 세 번째 INSERT 명령에서 에러가 발생했다고 치면, 앞서 실행한 두 개의 INSERT 명령에 의해 추가된 데이터를 DELETE 명령으로 삭제하는 처리가 필요하다.

2. 롤백과 커밋

  • 이처럼 몇 단계로 처리를 나누어 SQL 명령을 실행하는 경우에 트랜잭션을 자주 사용한다.
  • 트랜잭션을 사용해서 데이터를 추가한다면 에러가 발생해도 트랜잭션을 롤백(rollback)해서 종료할 수 있다.
  • 롤백하면 트랜잭션 내에서 행해진 모든 변경사항을 잃었던 것으로 할 수 있다.
  • 아무런 에러가 발생하지 않는다면 변경사항을 적용하고 트랜잭션을 종료하는데, 이때 커밋(commit)을 사용한다.
트랜잭션을 롤백하면 변경한 내용이 적용되지 않는다!

자동커밋

  • 트랜잭션을 사용해서 데이터를 추가할 때는 자동커밋을 꺼야 한다.
  • mysql 클라이언트에서 명령을 실행할 때는 자동커밋이 켜져 있는 상태이다.
  • INSERTUPDATE, DELETE가 처리될 때마다 트랜잭션은 암묵적으로 자동커밋 상태로 되어 있다.
  • 자동커밋을 끄기 위해서는 명시적으로 트랜잭션의 시작을 선언할 필요가 있다.
  • 트랜잭션을 시작할 때는 START TRANSACTION 명령을 사용한다.

트랜잭션 시작

START TRANSACTION
  • 앞서 언급한 것처럼 트랜잭션을 종료하기 위해서는 변경된 내용을 적용한 후에 종료하는 '커밋'과 적용하지 않고 종료하는 '롤백'의 두 가지 방식이 있다.
  • 커밋할 때에는 COMMIT 명령을 사용한다.

트랜잭션 내에서 실행한 명령을 적용한 후 종료

COMMIT
  • 롤백은 ROLLBACK 명령을 사용한다.

트랜잭션 내에서 실행한 명령을 파기한 후 종료

ROLLBACK
  • 트랜잭션 내에서 실행된 SQL 명령은 임시 데이터 영역에서 수행되다가, COMMIT 명령을 내리면 임시 데이터 영역에서 정식 데이터 영역으로 변경이 적용된다고 생각하면 된다.
  • ROLLBACK 명령을 내리면 임시 데이터 영역에서의 처리는 버려진다.

36강 트랜잭션의 커밋과 롤백

다음 예제에서는 트랜잭션을 사용해 발주처리를 한다. 에러가 발생하지 않은 경우의 사례로, 트랜잭션은 COMMIT을 이용해 종료한다.

트랜잭션 내에서의 발주처리

START TRANSACTION;
INSERT INTO 주문 VALUES(4, '2014-03-01', 1);
INSERT INTO 주문상품 VALUES(4, '0003', 1);
INSERT INTO 주문상품 VALUES(4, '0004', 2);
COMMIT
  • 이렇게 트랜잭션을 시작해서 SQL 명령을 실행하고 COMMIT 또는 ROLLBACK 명령으로 트랜잭션을 종료하는 일련의 처리방법을 '트랜잭션을 걸어서 실행한다' 또는 '트랜잭션 내에서 실행한다'라고 말한다.
트랜잭션을 사용해서 처리하는 것으로 간단히 데이터를 관리할 수 있다!

3. 트랜잭션 사용법

  • 발주처리와 같은 데이터 등록처리 과정에서는 대부분 트랜잭션 내에서 여러 개의 SQL 명령을 실행하게 된다.
  • 다만 하나의 명령에 트랜잭션을 걸어 실행하는 것은 별로 의미가 없다.
  • 트랜잭션 내에서 실행하는 복수의 SQL 명령은 세트 단위로 유효/무효가 된다.
  • 다시 말하면, 반드시 세트로 실행하고 싶은 SQL 명령을 트랜잭션에서 하나로 묶어 실행한다는 것이다.
  • ROLLBACK은 에러가 발생한 경우 변경사항이 적용되지 않도록 하는 목적으로 주로 사용하지만, 에러가 발생하지 않아도 ROLLBACK을 하면 변경한 내용은 파기된다.
  • 반대로 에러가 발생하더라도 COMMIT을 하면 문제없이 실행된 SQL 명령의 변경사항은 데이터베이스에 그대로 반영된다.
세트로 실행하고 싶은 SQL 명령은 트랜잭션 내에서 실행한다!
  • 트랜잭션을 시작할 때 사용하는 명령은 START TRANSACTION이라고 설명했지만 이것은 MySQL의 경우에 적용된다.
    • MySQL에서는 START TRANSACTION 외에도 BEGIN을 사용할 수 있다.
  • SQL ServerPostgreSQL에서는 BEGIN TRANSACTION 명령을 사용한다.
  • Oracle이나 DB2에서 트랜잭션을 시작하는 명령은 따로 없다. 이 또한 표준화가 진행되지 못한 부분이다.
  • 자동커밋은 클라이언트 툴의 기능이다.
  • 미들웨어도 데이터베이스 접속 시 대개 자동커밋을 한다.
  • 한편, 데이터베이스 서버에서는 언제나 트랜잭션을 걸 수 있는 상태로 SQL 명령이 실행된다.
  • 트랜잭션을 사용할 경우에는 접속형태나 클라이언트 툴의 자동커밋 사용 여부 등, 트랜잭션 관련 기능을 파악해 둘 필요가 있다.
  • DELETE 명령은 삭제 여부에 관해 사용자에게 확인하지 않는다고 설명했다.
  • 불친절한 시스템이라고 생각할 수도 있으나, DELETE 명령을 트랜잭션 내에서 실행하는 경우에는 ROLLBACK으로 삭제를 취소할 수 있다.
  • 단, 자동커밋으로 되어있는 경우에는 주의해야 한다. ROLLBACK으로 취소할 수 있는 것은 트랜잭션 내에서 실행했을 경우에 한해서이다.