23. 에러 방어하기 2

data_hamster·2023년 4월 26일

학습주제
에러 방어하기 2

학습내용
오류가 발생할 수 있는 또 다른 상황을 가정해본다.

A와 B가 이 화면을 보면서 완전히 동시에 둘다 녹차를 선택하고 vote를 선택했다고 가정한다. 그리고 둘은 각기 다른 장고서버에 접속해 있다고 가정한다.
일반적으로도 하나에 DB에 접속하는 여러대의 서버를 운영하기 때문에 가능한 상황.
A서버, B서버라고 가정한다. 두 서버는 같은 DB에 연결되어 있다.

과정은,

  • question_id를 가지고 question을 가져온다.
  • 가져온 question으로 choice를 가져온다.
  • choice를 가져와서 장고 서버 메모리에 로드한다.
  • 동시에 vote가 일어나므로


    각기 서버 메모리에서 1씩 증가한 상황.
  • .save()명령을 내리면 votes의 내용을 1로 바꾸라는 명령을 A,B서버에서 각각 DB로 내리가 된다.
  • 투표는 두명이 했는데, 두개의 1로 바꾸라는 명령이 들어와, votes의 count는 1이 된다.
  • 이를 해결하기위해 vote += 1 연산을 서버 메모리에서 하는 것이 아니라 DB에서 하도록 하면된다.

DB에게 너가 가지고 있는 vote를 1증가시키라고 하면 서버는 여러개더라도 DB는 1개이기 때문에 동시에 실행한 명령이 동시에 DB에서 실행될 수는 없다. 무엇 하나가 먼저 시행된다.

selected_choice.votes는 메모리로 로드한 값이다. 따라서 직접 DB에 접근하는 방식으로 바꾸려 한다.

selected_choice.votes = F('votes') + 1

F('votes')에서 F는 바로 DB에서 votes 값을 읽어서 1 증가시키라는 의미
F도 별도로 import 해야한다.
from django.db.models import F


녹차를 두번 선택한 votes가 증가한 것을 확인.

이는 1이 증가하는 요청을 잘 받아들였는지 확인한 것. 우리가 원하는 동시에 들어온 요청을 잘 처리했는지에 대한 확인을 해야한다. 많은 사용자가 동시에 접속한 상황.

어려운 점

selected_choice.votes = F('votes') + 1 보통 바꿀 값을 좌변에 넣는데, 여기선 우변에 넣어도 적용되는 모습이다. -> 아님
https://blog.myungseokang.dev/posts/django-f-class/
DB에 적용되는 SQL 쿼리문을 생성함. .save()시 그 쿼리문으로 바로 DB 값을 증가시킴.

주의. .save()를 할 때마다 값이 증가하기 때문에 이를 위한 조치도 필요함.

profile
반갑습니다 햄스터 좋아합니다

0개의 댓글