트랜잭션의 필요성을 느낄 수 있는 예시가 바로 계좌이체이다. 계좌이체를 진행하는 도중 예기치 못한 문제가 발생하여 내 계좌에서는 돈이 빠져나간 것으로 기록되고 상대방의 계좌에는 입금되지 않은 것으로 기록되는 경우 정말 큰 문제일 것이다. 이런 문제가 발생하지 않도록 해주는 개념이 트랜잭션이다. 중간에 문제가 발생한다면 내 계좌에서 돈이 빠져나가기 전으로 돌아간다던지 성공적으로 계좌이체를 보장해주는 것이다.
트랜잭션은 원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 지속성(Durability) 을 모두 만족해야 하며, 각 단어들의 첫 글자를 모아 ACID 특성
이라고 한다
트랜잭션 실행 도중에 문제가 발생했을 경우, 중단된 상태가 아닌 모두 실패하거나, 모두 완성 둘 중 하나의 상태가 되어야 합니다. 즉 100개 명령어로 구성된 트랜잭션 중 99개 완료 1개 실패가 된다면, 이는 무조건 실패로 간주하여 트랜잭션 시작 전 상태로 돌려야 합니다. 또한, 100개 모두가 성공했을 시 트랜잭션은 성공합니다. 따라서 중간상태란 없습니다.
일관성이란 트랜잭션 완료 후에도 데이터베이스가 일관된 상태로 유지되어야 합니다. 예를 들어 계좌이체를 성공적으로 실행했다면, A계좌의 잔액과 B계좌의 잔액의 합이 트랜잭션 실행 전의 합과 동일해야 합니다.
고립성이란 하나의 트랜잭션이 실행하는 도중에 변경한 데이터는 이 트랜잭션이 완료될 때까지 다른 트랜잭션이 참조하지 못하게 하는 특성입니다. 하나의 트랜잭션이 A라는 계좌에서 작업을 하고 있다면, 다른 트랜잭션이 A계좌에 대해 참조하거나 관여 할 수 없고 작업이 끝날 때까지 대기하거나 해야합니다.
지속성은 트랜잭션이 완료되면, 주기억장치가 아닌 디스크와 같은 보조기억장치에 저장되거나 그렇지 않더라도 시스템 장애가 회복되고 난 후에 어떠한 형태로든지 그 데이터를 복구 할 수 있게 해야함을 뜻합니다.
"@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
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
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