[Django] 트랜잭션 - atomic()

JinUk Lee·2024년 4월 22일
0

DRF 학습하기

목록 보기
53/57
post-custom-banner

개요

atomic() 에 대해 알아본다.

atmoic()을 사용하는 이유

django는 기본적으로 auto commit이다.


def atomic_test(request):

    post = Post.objects.get(pk=1)
    post.read_count+=1
    post.save()
    post.read_count+='awe'
    post.save()
    return JsonResponse({"set":post.read_count})

이러한 코드가 있다고 해보자.

read_countint 이므로 당연히 문자열을 더하는 작업은 오류가 발생한다.

그러나 해당 함수를 실행하면 오류가 발생하기 직전인 post.read_count+=1 까지는 db에 적용되는 것을 볼 수 있다.

따로 명시가 안되어있으므로 쿼리를 날리는 코드를 읽은 후에 바로 commit가 된다는 것이다.

문제는 예시와 같이 오류가 발생했을때, DB에 영향이 갈 수 있으므로 트랜잭션의 ACID에서 원자성에 위배된다.

그래서 원자성을 따르기 위해 atomic()가 사용된다.

사용법

atomic() 는 데코레이터와 with문 2가지 방식으로 사용된다.

# 데코레이터
from django.db import transaction

@transaction.atomic
def atomic_test(request):

    post = Post.objects.get(pk=1)
    post.read_count+=1
    post.save()
    post.read_count+='awe'
    post.save()

    return JsonResponse({"set":post.read_count})

데코레이터는 위와 같이 작성하며, 해당 함수를 실행할 경우 오류가 발생하고 db는 rollback 되어 그대로 남아있는다.

# with문

def atomic_test(request):

    post = Post.objects.get(pk=1)
    post.read_count+=1
    post.save()

    with transaction.atomic():
        post = Post.objects.get(pk=1)
        post.read_count+=5
        post.save()
        post.read_count+='asasf'
        post.save()

    return JsonResponse({"set":post.read_count})

트랜잭션으로 묶을 부분의 코드를 with문으로 감싸준다.

코드를 위에처럼 작성했을 경우, 위에는 auto commit, with문 내부는 atomic() 속성을 가지므로, 오류가 발생하더라도 auto commit 부분은 db에 반영되고 with문 내부는 반영되지 않고 roll back된다.

profile
개발자 지망생
post-custom-banner

0개의 댓글