차근차근/Oracle

NEXTVAL , CURRVAL

예쁜꽃이피었으면 2022. 3. 31. 11:58

 

NEXTVAL : 오라클 시퀀스값 증가

CURRVAL : 현재 시퀀스값 조회

 

 

https://mine-it-record.tistory.com/62

 

[ORACLE]오라클_시퀀스(NEXTVAL , CURRVAL) 사용법

일단 NEXTVAL 와 CURRVAL을 사용하기에 앞서 시퀀스를 생성하고 오도록 하자. (https://mine-it-record.tistory.com/61) [ORACLE]오라클_시퀀스(Sequence) 생성 / 수정 / 삭제 시퀀스(Sequence) - 유일한 값을 생..

mine-it-record.tistory.com

 

 

 

MYBATIS를 사용하면 SELECT KEY 와 함께써서

데이터를 넣고 바로 가져오는 경우가 있을 수 있다.

 

https://deeplify.dev/back-end/spring/select-key

 

[Spring/스프링] Mybatis selectKey 사용 방법

스프링 Mybatis에서 selectKey 사용하는 방법에 대해서 소개합니다.

deeplify.dev

 

 

이전에도 이런 식으로 사용을 해야했던..경우가 있었는데..

항상 궁금했던 것이 

동시에 INSERT되서 다른 키값을 가져오면 어쩌나 하는.. 걱정이었다.

실무에서도 어쩔 수 없이 사용을 한번 했었고

공부하는 친구들끼리 프로젝트를 진행할때도 한번 이런 경우가 있었다. (그때는 불안해서 트랜잭션을 적용했던걸로 기억한다..이 때 멘토분께 질문을 했을 때..그럴 수 있겠다는 답변을 받았고.. 해결방법은 듣지 못했다... 실무가 아니라서 그냥 지나치셨던 걸까..)

그 후에 같은 상황을 만나면 insert할 때 넣었던 데이터를 가지고

다시 select를 해서 key값을 가져왔었다.

 

시간이 지나서 다시 같은 코드를 만나니.. 또 다시 의문이 생긴다..


 

 

select key 를 사용하면

채번한 값을 객체에 저장한 후 그 값을 insert에 사용하므로, 멀티스레드 상황에서도 안전하게 값을 가져올 수 있다라는 글을 보았는데.. 

insert 후 select하는 경우에도 동일하게.. 적용되는 부분일까? 

 

selectkey , 멀티스레드 , 트랜잭션  이런 단어로 검색을 하다가 보게 된 내용

  • CURRVAL NEXTVAL을 호출한 세션에서 호출해야 한다.

https://ehdvudee.tistory.com/43

 

Oracle/Tibero CURRVAL 사용 주의사항

서두 CURRVAL을 잘못 사용할 경우, 끔찍한 상황이 도래될 수 있다. 정말 기본적인 사항을 간과했습니다... 오류 WARN  [org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory] (default task-10) I..

ehdvudee.tistory.com

더 알아보자

 

 


https://okky.kr/article/348698

 

OKKY | ORACLE에서 시퀀스.currval 질문입니다.

스프링 사용중입니다. DAO service 객체에서 게시판 글쓰기와 첨부파일을 Transaction 해놨는데요, Transactional Override public void regist(BoardVO board) throws Exception { // TODO Auto-generated method stub dao

okky.kr

http://www.gurubee.net/article/61086

 

스프링 게시판 insert 문제

글등록 할때 본문작성폼이랑 추가작성폼이 따로있는데 등록시 서로 다른 테이블로 들어갑니다. 스프링+마이바티스본문 글은 시퀀스로 저장이됩니다. I..

www.gurubee.net

꽤 오래전 글인데.. 왜 이제 봤지.. 

무튼 내 무지에서 비롯된.. 질문이었으며 그냥 select key 쓰면된다..

 

https://okky.kr/article/348698
이 질문에 대한 답 ]

세션을 하나로 만들었기 때문에 nextval 이후 currentval 을 가져올 수 있게 된 것이지 같은 값을 바라보고 있다고 장담할 수 없습니다.( => 댓글 : 세션을 하나로 만들어서가 아니라, currval 자체가 세션에 종속적이라 해당 세션에서 마지막으로 nextval 한 값을 보장합니다. )
왜냐하면 시퀀스는 트랜잭션 영향을 안받기 때문입니다.

정석은 select 로 nextval 값을 가져온 뒤 그 값을 가지고 insert 두 번 할 때 매개변수로 넣어주는 것입니다. mybatis 에서는 selectkey 로 이 작업을 해줄 수 있습니다.

트랜젝션 영향을 받지 않는다는 것은 시퀀스에 lock 이 걸리지 않는다는 이야기입니다. nextval 을 한 뒤 currval 을 하는 찰라의 시간 사이에 다른 연결에서 nextval 을 하면 문제가 됩니다.(=>댓글 : 다른 세션에서 currval 간섭할 수 없습니다.)
select 로 nextval 이 적용된 값을 받아올 수 있기 때문에 이런 식으로 먼저 채번부터 하면 다른 요소가 개입될 일이 없고, mybatis 에서도 버전에 따라 이용방법이 다르긴 하지만 <selectKey> 로 insert 전에 채번을 해주는 기능이 있습니다.

원래 세션 단위로 currval 을 제공하기 때문에 언급한 문제는 사실 거의 일어나지 않습니다. 하지만 만약의 경우를 대비한 안전한 코딩 습관 때문에 알려드린 겁니다.
그리고 이렇게 selectKey 을 쓰는 이유가 또 있는데, 통상적으로 insert 후 해당 sequence 을 반환받아야 하는 경우가 많고 nextval 을 select 시 사용해서 먼저 채번하면 트랜젝션을 걸 필요가 사라져 부하가 줄기 때문입니다.

currval 을 사용하지 못하는 경우에는 위처럼 selectKey를 사용하시면 됩니다. 그렇지만 위 같은 경우는 둘 다 insert문이기에 굳이 selectKey를 사용하지 않아도 됩니다.

 

아무튼 ibatis의 selectKey 자체가 시퀀스의 동시성을 보장해주는 어마어마한 역활을 하는 것은 아닙니다. 그냥 결과값 리턴 정도로 보면 됩니다.


아울러, 제 경험담을 말씀드릴께요.

본문처럼 코딩을 해서 별 문제가 없었고 서비스에도 큰 문제가 없었습니다. 오픈도 했구요.

 

다만, SM 에서 테스트 케이스 넣고 뭐 다른 로직 추가한다고 AOP 로 중간 가로채기 하고, 이것저것 하면서 nextval 을 중간에 끼워넣어버려서 sequence 가 꼬인 적이 있었네요.

SM 만 된통 깨지면 될 일 같았지만, SI 개발자들도 된통 깨졌어요. 프로젝트 초기에 가이드로 먼저 생성해서 값을 파라매터로 가지고 다니라고 했었거든요. 전 그 때 초보라 무슨 의미인지 잘 몰랐었는데 한 번 겪고 나니까 무슨 말인지 알겠더라구요.

 

코드를 나만 만지면 발생 안할 가능성이 거의 100%죠. 다만, 모든 경우의 수를 열어두는 것도 필요합니다. 굳이 쉬운 방법으로 더 탄탄한 코딩이 가능하다면 원리의 이해나 겉으로 드러난 문제에 대한 해결에만 집착할 필요는 없다고 봐요.

 

코딩은 사람이 하는 것이고, 협업이 되는 행위라는 걸 생각하면 먼저 시퀀스를 얻고난 다음 insert 나 update 을 하는게 좋다고 봅니다. 제가 당해보니 참 쓰라린 기억이 되더라구요.



같은 세션내에서 트랜잭션처리된 nextval과 currval은

절대로 외부의 영향을 받지 않는다는 건가요?

 

만약 영향을 받지 않는다면, 같은 세션에 있는 트랜잭션에서

nextval 후에 어떠한 인터셉트에 의해 인터셉트가 진행돼서 어떤 로직이 수행되고,

그 다음 currval이 수행된다면 이런 경우에도 한 세션이기 때문에 영향을 받지 않는건가요?


==> 
nextval은 아니고 currval은 해당 세션에 종속됩니다.

ex)
2개의 세션에서서 (A,B) 동시에 접속한다면 

A세션에서 
1. kk.nextval ----------- 1 
2. kk.currval ----------- 1 
--------------------------- 
B세션에서 nextval 후에 A세션에서서 
3. 2. kk.currval ----------- 1 
"1"로 나타납니다.. 

B세션에서 
1. kk.nextval ----------- 2 
2. kk.currval ----------- 2 

currval 값은 nextval값을 생성한 세션에 독립적입니다.



http://www.gurubee.net/article/61086
에 대한 답 ]

- 한 세션에서 nextval 한 Current한 값을 가지고 있기 때문에 상관없어요~


org.springframework.jdbc.UncategorizedSQLException
예외 메시지 : SqlMapClient operation; uncategorized SQLException for SQL []; SQL state [72000]; error code [8002]; --- The error occurred in game/dao/ibatis/GameList.xml. --- The error occurred while applying a parameter map. --- Check the insertContGameList-InlineParameterMap. --- Check the statement (update failed). --- Cause: java.sql.SQLException: ORA-08002: sequence GAME_SEQ.CURRVAL is not yet defined in this session ; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException: --- The error occurred in game/dao/ibatis/GameList.xml. --- The error occurred while applying a parameter map. --- Check the insertContGameList-InlineParameterMap. --- Check the statement (update failed). --- Cause: java.sql.SQLException: ORA-08002: sequence GAME_SEQ.CURRVAL is not yet defined in this session

currval 은 nextval 을 한 세션에서만 사용할 수 있습니다.
해당 오류는 nextval 안한 상태에서 currval 해서 나는 오류입니다.

-
nextval값을 먼저 조회해서 결과 seq값을 리턴 받은 다음에 저장 하세요!!

그럼 max로 값도 안 찾아와도 되고!!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형