MongoDB Pipeline을 활용한 데이터 실시간 수정

균비·2021년 2월 11일
0

mongodb

목록 보기
2/2

TL;DR

DB상 동시 수정이 필요한 경우 조회 -> 수정 시 시간차로 인한 오류가 발생할 수 있음.
따라서 MongoDB Pipeline 방식을 활용하여 현재 데이터 조회하고 이를 기반으로 수정 값을 업데이트 하는 방법을 은행 출금 알고리즘에 적용함.

(구글에 검색했을 때에는 조회 -> 수정 밖에 안나옴. 못찾은 것일수도.. (99%))

pipeline 미사용 (조회 -> 수정)


const account = require("../model/account");

...

const withdrawl = function(req, res, next) {
  const { amount } = req.body;
  const { accNum } = req.fullAccInfo;
  
  async.waterfall([
  	(cb) => {
      account.find({
        accNum
      })
      .then(result => cb(null, result))
      .catch(e => cb(e));
    },
    (prevVal, cb) => {
      account.updateOne({
        accNum
      }, {
      	remain: prevVal.remain - amount
      })
      .then(result => cb(null, result))
      .catch(e => cb(e));
    }
  ], (err, result) => {
  	if (err || result.modifiedCount < 1) {
      console.error(err);
      return res.status(500).end(`Internal Server Error`);
    }
   	next();
  })
}

문제점 인식

위 과정대로 작성시 발생하는 문제점이 있었다:

  1. 코드 길이가 길어짐
  2. 불필요한 데이터들을 많이 불러옴 (find 옵션에서 filtering 할 수 있긴 하지만, 이 이전에도 계좌 확인과정으로 find를 한번 처리하기 때문에 큰 효용이 없음.)
  3. 데이터를 불러오고 수정하는 사이 시간동안 기존 데이터가 변경될 수 있음 ( 불러온 데이터를 기반으로 수정하기 때문에 가령 10,000원이 있던 통장에서 5,000원을 출금하던 중 먼저 7,000원이 출금처리가 된다면 기존 잔액 3,000원이 아닌 체크된 10,000원에서 변경된 5,000원이 최종 잔액으로 남음 ==> 오류발생(!!!) ) (*****)

잔액: 10,000원 --------------------

7,000원 출금요청(요청A) ---------------

5,000원 출금요청(요청B) ---------------

요청 A 출금 가능여부 확인됨--------------

요청 B 출금 가능여부 확인됨 -------------

요청 A 출금됨 (잔액: 3,000원) -------------

요청 B 출금됨 (잔액: 5,000원) -------------

==> 최종잔액 (5,000원) > (은행입장) 실제 고객 보유 금액보다 2,000원 손해

==> mongoose updateOne 정식 문서 중 pipeline 지원 여부를 확인하여 pipeline을 사용한 즉시변경 방식을 사용하기로 결정.

pipeline 사용 작성


const account = require("../model/account");

...

const withdrawl = function(req, res, next) {
  const { amount } = req.body;
  const { accNum } = req.fullAccInfo;
 
  
  account.updateOne({
    accNum
  }, [
    {
    	$set: { remain: { $subtract: [ "$remain", amount ] } }
    }
  ])
}

조회과정 없이 데이터를 실시간으로 수정할 수 있음. 실시간 수정 덕분에 '조회 -> 데이터 수정중 값 변경으로 인한 결과 상이'를 막을 수는 있지만, 아직 subtract 과정 이후 -로 처리될 때에는 수정을 하면 안되는데, 아직 이를 해결하지 못해 pipeline상에서 한번에 처리하는 방법을 알아보아야 할듯 함.

profile
뒹굴뒹굴 고3 개발자!

0개의 댓글