작성
·
164
1
안녕하세요, 선생님
초반에 transaction을 제거하고 성능을 높이는 방법을 보여주셨는데, transaction을 적용하기 이전의 코드와 1:52초 즈음에 알려주시는 코드의 차이가 궁금합니다. mongodb에서 직접 수정을 하냐 아니면 nodejs로 데이터를 가져와서 조작을 하냐의 차이 때문에 성공 실패가 갈리는거죠?
제 생각에는 아무래도 nodejs로 데이터를 가져온 상태에서 조작을 한다면, 조작해서 저장하는 시점엔 데이터베이스의 내용이 달라져서 덮어씌워지는 건데, 반대로 직접 데이터베이스에서 조작하면 항상 데이터베이스의 현재 내용물을 조작하니깐 일관성이 생기는거죠. 제가 잘 이해한게 맞을까요?
답변 2
0
오 __v를 통해서 대조를 하는군요! 하나 더 배운 것 같습니다. 업데이트 보장을 위해서는 트랜잭션을 하라는 말씀이시군요. 빠르고 자세한 답변 주셔서 감사합니다!
0
daehyun님 안녕하세요 :)
맞습니다. 불러와서 수정을하게 되면 살짝의 공백이 생기는데 이 때 다른 요청이 해당 문서를 수정/삭제 해버린다면 일관성 문제가 발생됩니다. 그래서 mongoose가 .save() 할 때 내부적으로 문서의 __v를 대조합니다. 문서를 불러왔을 때의 __v: 3이었다면 .save()하는 순간에도 __v:3이어야 하는데 만약 __v:4이면 그 사이에 다른 요청이 업데이트 처리를 한거기 때문에 오류를 발생시킵니다. 이렇게 되면 해당 문서 한해서는 잘못된 데이터(다른 요청에 의해 수정된) 수정을 방지할 수는 있습니다. 하지만 이런 안전장치가 있다고 하더라도 여러개의 문서를 수정한다면 일관성 문제가 생길 수 있어요. 2개의 문서를 수정하는데 하나는 문제 없이 수정이 되었는데 두번째로 수정된 문서의 __v가 달라서 오류가 발생하는 경우가 충분히 있을 수 있죠. 그래서 이런 경우 Transaction을 사용하면 문제가 해결됩니다. 수정하는 문제들이 락에 걸리기 때문에 다른 요청이 수정을 하려면 Transaction이 끝나야만 가능하니깐요.
두번째 방법이 find를 생략하고 바로 업데이트를 요청하면서 디비의 요청 수가 줄어들어요. 그래서 성능이 조금 더 좋을 수 있지만 첫번째 방법을 하더라도 Transaction을 사용하지 않으면 성능이 강의에서처럼 크게 차이나진 않을거에요. Transaction이 더 부하를 일으키기 때문에 결제와 같은 정말 중요한 처리가 아니라면 가급적이면 Transaction을 사용하지 않는 방법을 찾아보길 권장한겁니다. 두번째로 보여드렸던 방법은 백엔드로 불러오지 않고 몽고디비에서 즉시 업데이트 하는 작업이기 때문에 문서 각각의 버전 문제는 고민 하지 않아도 되요. (__v 대조 할 필요 없음) 다만 Transaction을 사용하지 않았기 때문에 Blog, Comment중 하나만 업데이트가 될 가능성이 (매우매우 낮지만)없진 않죠. 만약 100% 둘 다 업데이트 성공을 보장을 해야한다면 두번째 방법에도 Transaction을 사용하셔야할건데요. 그러면 이 경우도 첫번째만큼은 아니더라도 시간이 상당히 소요될거에요.
그리고 참고로 save()로 하든 update()로 하든 두 방법 모두 atomic합니다. save()로 하면 __v로 인해 요청이 실패할 수 있을뿐인겁니다. save(), update()가 한 문서의 여러 값들을 수정할 수 있는데 이 수정들이 모두 처리되거나 모두 실패한다는 면에서 atomic하다는겁니다. 한 문서의 3개의 값을 수정했는데 2개만 성공하고 하나는 업데이트 못하는 상황은 없습니다. 이건 Transaction과 별개입니다.