Django | 트랜잭션(Transaction)

김민호·2021년 10월 23일
0

DJANGO

목록 보기
13/18
post-thumbnail

트랜잭션(Transaction)

1. 정의

  • 데이터베이스의 상태를 변화시키기 해서 수행하는 작업의 단위
  • 하나의 논리적인 작업 단위를 구성하는 연산들의 집합
  • 하나의 실행 단위로서 모든 과정들이 성공되어야 데이터베이스의 상태가 변하게 되고, 중간에 실패하면 기존의 작업들은 모두 rollback된다

2. 필요성

트랜잭션의 필요성을 느낄 수 있는 예시가 바로 계좌이체이다. 계좌이체를 진행하는 도중 예기치 못한 문제가 발생하여 내 계좌에서는 돈이 빠져나간 것으로 기록되고 상대방의 계좌에는 입금되지 않은 것으로 기록되는 경우 정말 큰 문제일 것이다. 이런 문제가 발생하지 않도록 해주는 개념이 트랜잭션이다. 중간에 문제가 발생한다면 내 계좌에서 돈이 빠져나가기 전으로 돌아간다던지 성공적으로 계좌이체를 보장해주는 것이다.

3. ACID 특성(ACID property)

트랜잭션은 원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 지속성(Durability) 을 모두 만족해야 하며, 각 단어들의 첫 글자를 모아 ACID 특성 이라고 한다

1) 원자성(Atomicity)

트랜잭션 실행 도중에 문제가 발생했을 경우, 중단된 상태가 아닌 모두 실패하거나, 모두 완성 둘 중 하나의 상태가 되어야 합니다. 즉 100개 명령어로 구성된 트랜잭션 중 99개 완료 1개 실패가 된다면, 이는 무조건 실패로 간주하여 트랜잭션 시작 전 상태로 돌려야 합니다. 또한, 100개 모두가 성공했을 시 트랜잭션은 성공합니다. 따라서 중간상태란 없습니다.

2) 일관성(Consistency)

일관성이란 트랜잭션 완료 후에도 데이터베이스가 일관된 상태로 유지되어야 합니다. 예를 들어 계좌이체를 성공적으로 실행했다면, A계좌의 잔액과 B계좌의 잔액의 합이 트랜잭션 실행 전의 합과 동일해야 합니다.

3) 고립성(Isolation)

고립성이란 하나의 트랜잭션이 실행하는 도중에 변경한 데이터는 이 트랜잭션이 완료될 때까지 다른 트랜잭션이 참조하지 못하게 하는 특성입니다. 하나의 트랜잭션이 A라는 계좌에서 작업을 하고 있다면, 다른 트랜잭션이 A계좌에 대해 참조하거나 관여 할 수 없고 작업이 끝날 때까지 대기하거나 해야합니다.

4) 지속성(Durability)

지속성은 트랜잭션이 완료되면, 주기억장치가 아닌 디스크와 같은 보조기억장치에 저장되거나 그렇지 않더라도 시스템 장애가 회복되고 난 후에 어떠한 형태로든지 그 데이터를 복구 할 수 있게 해야함을 뜻합니다.

4. Save Point

  • 트랜잭션의 길이가 길면 트랜잭션의 중간 지점에 수정내용을 반영하는 포인트를 만드는데, 이를 SAVEPOINT(저장점)라고 한다. 트랜잭션이 잘못되어 처음부터 다시 실행해야 할 경우 트랜잭션의 처음이 아니라 SAVEPOINT까지 되돌아가면 트랜잭션 전체가 ROLLBACK되는 것을 막을 수 있다. SAVEPOINT는 트랜잭션 안에 여러 개 만들 수 있다.

5. 사용방법

1) 데코레이터(decorator)를 이용한 트랜잭션(transaction)

  • 데코레이터를 이용하게 되면, 메서드 안에는 코드를 삽입할 필요없이 "@transaction.atomic" 이라는 데코레이터를 붙여주기만 하면 끝이다. django 에서 기본적으로 제공해주는 데코레이터이므로, 따로 모듈을 설치해줄 필요도 없다
from django.db import transaction

@transaction.atomic
def transaction_test(arg1, arg2):
	resume = Resume.objects.get(id = 1)
		
        resume.title        = 'title'
        resume.status       = 'status'
        resume.introduction = 'introduction'
        
        user_career = resume.usercareer_set.get(id = 1)
        user_career.company_name = 'company_name'
        
	# start transaction
    	resume.save()
    	user_career.save()
    	# end transaction

2. with 명령어를 이용한 트랜잭션

  • 메서드 전체가 아닌 메서드의 일부분만 트랜잭션으로 묶어줄 필요가 있을 때 사용한다. 트랜잭션으로 묶일 부분을 직접 지정해줘야 하지만 데코레이터와 마찬가지로 비교적 간단하게 처리가 가능하다
from django.db import transaction

def transaction_test(arg1, arg2):
	resume = Resume.objects.get(id = 1)
		
        resume.title        = 'title'
        resume.status       = 'status'
        resume.introduction = 'introduction'
        
        user_career = resume.usercareer_set.get(id = 1)
        user_career.company_name = 'company_name'
        
        education = resume.education_set.get(id = 1)
        education.university_name = 'university_name'
        
        resume.save() # 항상 save 처리, 예외 발생 시 에러 발생
        
        with transaction.atomic():
      	    # start transaction
            user_career.save()
            education.save()
            # end transaction

3. savepoint를 직접 지정해 주는 트랜잭션

  • 1번과 2번의 방법의 경우, 메서드 내에서(트랜잭션으로 묶여져있는) exception 이 발생하더라도 저절로 롤백이 되기 때문에 예외처리를 따로 해 줄 필요는 없다. 하지만 3번의 경우에는 savepoint 및 commit 지점을 직접 지정해 주기 때문에 예외처리 또한 별도로 처리해줘여 한다
from django.db import transaction

def transaction_test(arg1, arg2):
	resume = Resume.objects.get(id = 1)
		
        resume.title        = 'title'
        resume.status       = 'status'
        resume.introduction = 'introduction'
        
        user_career = resume.usercareer_set.get(id = 1)
        user_career.company_name = 'company_name'
        
        education = resume.education_set.get(id = 1)
        education.university_name = 'university_name'
        
        resume.save() 
        
        sid = transaction.savepoint()
        
        # start transaction
        try:
            user_career.save()
            education.save()

            transaction.savepoint_commit(sid)
            # end transaction
        except Exception:
            transaction.savepoint_rollback(sid) # 트랜잭션 내에서 에러 발생시 롤백

참고
https://limkydev.tistory.com/100
https://velog.io/@kho5420/Django-%EC%9E%A5%EA%B3%A0-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0

profile
개발자로서의 삶은 https://velog.io/@maxminos 에서 기록하고 있습니다 😀

0개의 댓글