본문 바로가기
DB

[DB] 트랜잭션(Transaction)

by 당코 2023. 1. 28.

트랜잭션

트랜잭션이란 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미한다.

쉽게 말하면 데이터베이스에서 트랜잭션은 하나의 거래를 안전하게 처리하도록 보장해 주는 것을 뜻한다.

만약 A에서 B로 계좌이체를 한다고 할 때 두 가지 작업이 하나의 작업처럼 동작해야 한다.

  1.  A의 잔고를 5000원 감소
  2.  B의 잔고를 5000원 증가

데이터베이스가 제공하는 트랜잭션 기능을 사용하면 1,2 둘 다 함께 성공해야 저장하고, 중간에 하나라도 실패하면 거래 전의 상태로 돌아갈 수 있다.

 

트랜잭션 ACID

트랜잭션은 ACID 하는 원자성(Atomicity), 일관성 (Consistency), 격리성(Isolation), 지속성(Durability)을 보장해야 한다.

  • 원자성: 트랜잭션 내에서 실행한 작업들은 마치 하나의 작업인 것처럼 모두 성공하거나 모두 실패해야 한다.
  • 일관성: 모든 트랜잭션은 일관성 있는 데이터베이스 상태를 유지해야 한다. 예를 들어 데이터베이스에서 정한 무결성 제약 조건을 항상 만족해야 한다.
  • 격리성: 동시에 실행되는 트랜잭션들이 서로에게 영향을 미치지 않도록 격리한다. 예를 들어 동시에 같은 데이터를 수정하지 못하도록 해야 한다. 격리성은 동시성과 관련된 성능 이슈로 인해 트랜잭션 격리 수준 (Isolation level)을 선택할 수 있다.
  • 지속성: 트랜잭션을 성공적으로 끝내면 그 결과가 항상 기록되어야 한다. 중간에 시스템에 문제가 발생해도 데이터베이스 로그 등을 사용해서 성공한 트랜잭션 내용을 복구해야 한다.

 

트랜잭션의 commit, rollback

데이터 변경 쿼리를 실행하고 데이터베이스에 그 결과를 반영하려면 커밋 명령어인 commit을 호출하고, 결과를 반영하고 싶지 않으면 롤백 명령어인 rollback을 호출하면 된다

두 가지 세션이 데이터베이스에 쿼리를 실행하는 경우를 살펴보겠다.

위와 같은 기본데이터에서 세션 1이 트랜잭션을 시작하는 경우는 조회결과가 다음과 같다.

세션 1에서 데이터를 insert 하여 DB에 저장을 하였고, 그 상태는 아직 임시상태로 남아있다.

따라서 다른 세션에서 데이터를 조회하였을 때 트랜잭션이 완료되기 전까지는 확인할 수 없게 된다.

세션 1이 신규 데이터를 추가한 후에 commit을 호출하면 새로운 데이터가 실제 데이터베이스에 반영되게 된다.

트랜잭션이 끝난 후에는 다른 세션에서도 추가된 데이터를 확인할 수 있다.

만약 세션 1이 신규 데이터를 commit 하지 않고 취소하고 싶으면 rollback을 하면 된다.

rollback을 호출하면 데이터베이스에 임시로 저장돼 있던 신규 데이터가 처음 상태로 복구된다.

수정하거나 삭제한 데이터도 rollback을 호출하면 모두 트랜잭션을 시작하기 직전의 상태로 복구된다.

 

자동 커밋, 수동 커밋

자동커밋

자동 커밋으로 설정하면 각각의 쿼리 실행 직후에 자동으로 커밋을 호출한다. 따라서 커밋이나 롤백을 직접 호출하지 않아도 되는 편리함이 있다.

set autocommit true; //자동 커밋 모드 설정
insert into member(member_id, money) values ('data1',10000); //자동 커밋
insert into member(member_id, money) values ('data2',10000); //자동 커밋

하지만 쿼리를 하나하나 실행할 때마다 자동으로 커밋이 되어버리기 때문에 우리가 원하는 트랜잭션 기능을 제대로 사용할 수 없다.

데이터베이스는 자동커밋을 default로 설정해 놓아 따로 설정하지 않아도 동작한다.

 

수동커밋

보통 자동 커밋 모드가 기본으로 설정된 경우가 많기 때문에, 수동 커밋 모드로 설정하는 것을 트랜잭션을 시작한다고 표현할 수 있다.

set autocommit false; //수동 커밋 모드 설정
insert into member(member_id, money) values ('data3',10000);
insert into member(member_id, money) values ('data4',10000);
commit; //수동 커밋

수동 커밋 설정을 하면 이후에 꼭 commit , rollback을 호출해야 한다.

수동 커밋 모드나 자동 커밋 모드는 한번 설정하면 해당 세션에서는 계속 유지된다. 중간에 변경하는 것은 가능하다.

 

DB 락

만약 세션 1에서 데이터를 수정하는 중에 커밋을 수행하지 않았는데, 세션 2에서 동시에 같은 데이터를 수정하게 되면 여러 가지 문제가 생긴다.

바로 트랜잭션의 원자성이 깨지는 것이다. 여기에 더해서 세션 1이 중간에 롤백을 하게 되면 세션 2는 잘못된 데이터를 수정하는 문제가 발생한다.

그래서 세션이 이 트랜잭션을 시작하고 데이터를 수정하는 동안에는 커밋이나 롤백 전까지 다른 세션에서 해당 데이터를 수정할 수 없게 하는 것이 DB 락이다.

데이터를 수정할 때에 락이 있어야만 수정이 가능하고 커밋을 할 때 락을 반납하게 된다.

락이 없을 경우 무한정 기다리는 것이 아닌 내부적으로 설정된 락 타임아웃까지 기다리고 그 후에는 오류를 발생시킨다.

다음과 같이 수동으로 설정할 수도 있다.

SET LOCK_TIMEOUT 60000;

 

출처 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-1/dashboard