본문 바로가기
백엔드/스프링+boot

Transaction, Transactional

by 임지혁코딩 2023. 12. 28.

@Transactional

 

이때 @Transactional이 왜 필요할까?

 

일단 예시부터. 은행에서 만원을 뺐는데, 상대방은 만원을 못받는 경우가 있을까? 없다.

이를 기본으로 트랜잭션의 성질을 보자 <sqld에서 봤었다>

1. Atomic(원자성)

돈을 빼는것과, 돈을 받는 작업이 한개의 트랜젝션으로 묶여서! 두 작업이 모두 성공하거나 모두 실패해서 빼긴 성공해씅나 받을때 에러가 나면, rollback 된다. 

<sqld에서 외웠던 원자성 고립성 지속성 일관성 이것들을, 실제 예시와 어떻게 그게 작동하는지를 보자>

 

2.일관성(COnsistency)

db저장된 파일은, 일정 규약을 따라야한다.

트랜젝션이 끝나는 점에서는 이러한 일관성이 맞춰저 있어야하고, commit이 끝나는 지점에서는 맞춰져 있어야한다.

예시로, 잔고는 0원 이상인데, 중간엔 0보다 적을수있지만 commit이 끝날때는 반드시 0보다 커야한다. 

 

3. 고립성(isolation)

sqld에서는 다른 트랜젝션의 접근 x -> repetable-read,등등.. 이렇게 고립 레벨을 가지고 있고, 가장 노픈 serializable단계까 되면, 한 시점에 한 트랜젝션만 처리가 가능하다 (당연히 성능이 떨어진다) 

실제 경우: 성능과 tradeoff관계.  

이렇게 통제를 해줘야한다. 

 

4. duriabilty(지속성)/ 영속성

commit이 한번 되었다면, 그 기록은 영원해야한다. 한번 지우는 commit을 했더라도, 넣었던 입력, 지웠던 입력 모두 기록이 남아있어야한다. ex)조선왕조실록처럼 지워라,도 지우라고혀샀다고 적는다.

의미 -> db내부적으로 오류가 발생했다면, 로그에 남기고, 그 로그 데이터 기반으로 db disk에 적는다.

만약에 오류가 발생했다면 로그를 확인하고 돌아갈 수 있게끔 하는 여지를 남겨두어야 한다. 

추가적인 의미 -> commit이 되어 로그로 남기지 않으면 db에 반영되지 않는다. 

(하지만 mysql는 auto commit이 되어 insert하면 바로 처리된다. 그래서 이 개념이 와닿지 않았던 것)

<합쳐서 ACID!> 

 

스프링의 트랜잭션 지원

@Transactional ? 자세히 보자

db에서 transaction을 가져오고. getTransaction, 거기서 trasaction.begin(), 그이후 db작업 , 그 이후 transaction.commit()

catch(Exception e){//exception 발생시! 만약에 만원 뺐더니 - 5000원이다 or 만원을 뺴고 나서 만원을 더했더니 에러가 났다. transaction.roolback(); } 이런식으로 발생된다. 

 

즉 , 3가지 부분을 따른다 . 1. buisnesslogic start ~end //일 하기 

어? 이거 AOP아닌가? <로직은 정해져있고 , 특정 포인트(join point)에 무슨 처리가 필요함을 작성> 

이러한 반복적인 logic들을 @Transactional을 통해서 ACID 특성을 고려해줄 수 있다. 

@Transactional이 동작하는 기반이 AOP 기반이다 . 

 

TransactionInterceptor이 있다. 이가 동작하면서, COMMIT,ROLLBACK 을 따라가게 된다. 

 

interceptor내부를 들여다 본 것. 

invoke? 만든 method를 불러주고 이 invoke하는 행위는 join point가 된다. AOP의 관점에서 봤을때 추가적인 method 등이 들어갈 수 있는 포인트가 된다. 

invokewithinTransaction. transaction을 필요하면 생성하고, 그 정보를 가져온다.

 

즉! 트랜젝션은 최소단위의 (쪼개질수없는) 업무처리의 단위이다! 

 

DB의 실제 값을 변경할때는 @TRANSACTIONAL( POST OR PUT OR PATCH등에서 쓰이겠지) 필요