백엔드 공부의 시작은 김영한님의 강의였는데, 여러 강의에서 거듭하여 트랜잭션 관리의 중요성을 강조하신 기억이 난다.

 

장고는 스프링과 달리 엔티티를 관리하는 Entitiy Manager 가 없다. 또한, 디폴트 설정이 auto commit이기 때문에 DB에 데이터를 쓰는 작업을 할 때, save와 update시 바로 바로 쿼리가 날아가게 된다.

 

따라서 여러 레코드를 한 번에 저장하는 로직의 경우에는 주의가 필요하다.

 

transaction atomic을 사용하면 모든 로직이 정상적으로 수행되었을 때만 커밋이 나가고, 오류가 난 경우에는 롤백이 되도록 할 수 있다.

 

사용법은 간단하니 구글링을 통해 사용하면 된다.

 

내가 기록하고자 하는 바는, 사용을 했음에도 불구하고 오류 상황에서 롤백이 제대로 먹히지 않는 부분이다.

 

의심되는 원인은 다음과 같다.

 

  1. 로직 내에서 DB를 2개 사용하고 있어서 -> 이 부분은 with transaction.atomic을 DB 2개에 모두 걸어주면 해결 된다고는 하는데 아직 테스트 못해봄
  2. 공통함수를 사용하는데, 함수 안에 try catch 문이 있는경우 -> transaction atomic 안에 try catch 가 존재하면 사용자가 에러를 처리했다고 생각하고 롤백을 안시킴
  3. thread를 사용해서 -> 데이터 생성 여러개를 할 때 성능이 너무 안나와서 쓰레드로 돌리는 경우가 있는데, 이 때는 db connection을 끊어주는 등의 추가 액션이 필요해 보임

여러가지 테스트를 통해 얻은 결과는 다음과 같다.

 
  1. 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 문 없이 사용해도 된다.
  2. 공통 함수로 사용하는 함수들 내부에 try catch가 있는 경우에는 원자성이 보장되지 않을 수 있다. try catch 를 사용하려면 with transaction.atomic 구문 밖에서 사용해아 하며, 내부에 try catch 가 존재하는 경우에는 사용자가 에러를 알아서 처리했다고 여겨 롤백이 제대로 되지 않을 수 있다.
  3. 한 번에 여러개의 레코드를 생성하거나 변경하는 경우 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

+ Recent posts