백엔드 공부의 시작은 김영한님의 강의였는데, 여러 강의에서 거듭하여 트랜잭션 관리의 중요성을 강조하신 기억이 난다.
장고는 스프링과 달리 엔티티를 관리하는 Entitiy Manager 가 없다. 또한, 디폴트 설정이 auto commit이기 때문에 DB에 데이터를 쓰는 작업을 할 때, save와 update시 바로 바로 쿼리가 날아가게 된다.
따라서 여러 레코드를 한 번에 저장하는 로직의 경우에는 주의가 필요하다.
transaction atomic을 사용하면 모든 로직이 정상적으로 수행되었을 때만 커밋이 나가고, 오류가 난 경우에는 롤백이 되도록 할 수 있다.
사용법은 간단하니 구글링을 통해 사용하면 된다.
내가 기록하고자 하는 바는, 사용을 했음에도 불구하고 오류 상황에서 롤백이 제대로 먹히지 않는 부분이다.
의심되는 원인은 다음과 같다.
- 로직 내에서 DB를 2개 사용하고 있어서 -> 이 부분은 with transaction.atomic을 DB 2개에 모두 걸어주면 해결 된다고는 하는데 아직 테스트 못해봄
- 공통함수를 사용하는데, 함수 안에 try catch 문이 있는경우 -> transaction atomic 안에 try catch 가 존재하면 사용자가 에러를 처리했다고 생각하고 롤백을 안시킴
- thread를 사용해서 -> 데이터 생성 여러개를 할 때 성능이 너무 안나와서 쓰레드로 돌리는 경우가 있는데, 이 때는 db connection을 끊어주는 등의 추가 액션이 필요해 보임
여러가지 테스트를 통해 얻은 결과는 다음과 같다.
- DB를 2개 사용하기 때문에 with transaction.atomic(using=DB_LMS_W): 와 같이 using 을 통해 어떤 DB의 원자성을 보장하려고 하는지 명시를 하게 된다. 해당 구문 내부에서 create나 update를 하는 경우에도 Schedule.objects.using(DB_LMS_W).create 와 같이 DB를 명시해주어야 한다. 현재 서버가 바라보고 있는 디폴트 DB인 경우에도 명시를 해주어야 원자성이 보장된다. 다만, 두 DB중 하나의 원장성만이 필요한 경우에는 with transaction.atomic, Schedule.objects.create 와 같이 using 문 없이 사용해도 된다.
- 공통 함수로 사용하는 함수들 내부에 try catch가 있는 경우에는 원자성이 보장되지 않을 수 있다. try catch 를 사용하려면 with transaction.atomic 구문 밖에서 사용해아 하며, 내부에 try catch 가 존재하는 경우에는 사용자가 에러를 알아서 처리했다고 여겨 롤백이 제대로 되지 않을 수 있다.
- 한 번에 여러개의 레코드를 생성하거나 변경하는 경우 Thread를 사용하는 경우가 있는데, Thread를 사용해도 원자성이 보장된다.
'Django' 카테고리의 다른 글
Django - HTTP Response Redirection (0) | 2022.02.02 |
---|---|
Django - @property 사용하기 (0) | 2022.01.09 |
Django - Crontab (Mac OS) (0) | 2021.11.18 |
Django - paging (0) | 2021.10.18 |
Django - N+1 Problem (0) | 2021.10.07 |