<개발 Tip> Mybatis에서 Sequence next가 안될 때

Posted by bbubbush on March 26, 2019

오라클 데이터베이스에는 Sequence라는 기능이 있습니다. 고유한 값을 생성해주는 객체인데요, 순차적으로 값을 증가시키며 값의 중복을 방지합니다.

이때 여러분 머리속에 떠오르는 개념이 Primary key 일 것 입니다. 실제로도 PK를 관리하기 위해 주로 사용됩니다.

본론

업무 중에 입력받은 데이터를 코드값으로 분류하여 각각 새로운 PK를 생성해야 하는 상황이 있었습니다. 예를 들어보겠습니다.

    for (int i = 0; i < 3; i++) {
        String newPk = sequenceMapper.getNewSequence(); // 새로운 pk값을 생성
        logger.debug("newPk >>> " + newPk);
    }

    ... (후략)새로운 pk값을 가지고 작업한다

위와 같은 코드가 있다면 어떤 결과가 나올까요? 과연 세번의 출력값이 모두 다른 pk를 갖게 될까요? 제 대답은 “그럴수도 있고 아닐수도 있다” 입니다.

이는 sequenceMapper의 getNewSequence SQL의 설정값에 따라 다른 결과가 나오기 떄문입니다. 별다른 옵션을 주지 않았다면 아마 같은 pk가 세 번 출력될 것 입니다.

아래 예제는 설정값의 차이를 어떻게 두는지에 대한 설명입니다.

// 일반적인 xml
<select id="getNewSequence" resultType="String">
    SELECT seq_pk.NEXTVAL
      FROM DUAL
</select>


// flushCache를 적용한 xml
<select id="getNewSequence" resultType="String" flushCache=true>
    SELECT seq_pk.NEXTVAL
      FROM DUAL
</select>

기본적으로 마이바티스는 cache를 통해 호출했던 쿼리의 결과값을 저장해 두었다가 후에 다시 요청이 오면 쿼리를 실행하지 않고 결과값만 바로 보내줍니다.

성능적인 측면에서 유용한 기능이지만 간혹 이와 같은 상황에서는 독이 되기도 합니다. 그렇기 때문에 상황에 따라 현명하게 선택할 수 있어야 합니다.

요약: Service에서 반복적인 쿼리문 호출은 캐시된 데이터를 넘겨받기 때문에 의도하지 않은 값을 받을 수 있다. 이럴땐 flushCache를 사용하는 것이 하나의 방법이 될 수 있다. 다만, 쿼리가 자원을 많이 소모하는 대량의 데이터를 가져온다면 캐시를 지우는 것이 현명한 방법인지 깊게 고민해볼 필요가 있다!