atomic()
에 대해 알아본다.
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_count
는 int
이므로 당연히 문자열을 더하는 작업은 오류가 발생한다.
그러나 해당 함수를 실행하면 오류가 발생하기 직전인 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된다.