개발이군고구마

[Spring/DB]Transaction 과 Lock (@Transactional 사용에 대한 궁금증을 시작으로) 본문

SERVER/Spring

[Spring/DB]Transaction 과 Lock (@Transactional 사용에 대한 궁금증을 시작으로)

김구황 2025. 3. 8. 13:58
728x90

1. 상황 

- Redisson 활용하여 트랜잭션 안에서 또 다른 분산락을 설정 중 

- @Transactional 사용시에도 락을 얻을텐데 동시에 여러 접속자가 같은 자원을 조회할 때, 왜 락이 제대로 잡히지 않는 것일까 궁금해짐 

 

 

2. 스프링의 트랜잭션

[스프링의 @Transactional]

- 프록시 패턴 (트랜잭션 추상화와 AOP)

호출될 때 요청을 가로채어 DB 커넥션을 얻고 트랜잭션 처리 시작 

서비스 단에서 일일이 커넥션 풀을 얻는 로직을 작성해줄 필요는 없이 프록시 객체에서 수행함 

 

- 트랜잭션 동기화 

일관된 처리 가능 (자식 트랜잭션 실패시 부모 트랜잭션까지 전파되어 롤백되는 기능)

 

 

* DB 커넥션 

- 커넥션 얻는 과정 

http://shuu.tistory.com/130

어플리케이션 시작 시점에 커넥션 풀에 이미 필요한 만큼의 커넥션이 생성되어 있음 

DB 드라이버를 통해 새로운 커넥션을 획득하는 것이 아니라, 이미 생성되어 있는 커넥션을 참조하여 사용 

 

 

 

3. 트랜잭션의 속성

[Isolation 격리수준 - Lock]

- Default  : 기본 격리 수준 

- READ_UNCOMMITED : 커밋되지 않은 데이터에 대한 읽기를 허용 DIRTY READ

- READ_COMMITED : 트랜잭션이 커밋이 확정 데이터만 읽기 허용 

- REPEATABLE_READ : 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터 Shared Lock (= 다른 사용자는 그 영역에 해당하는 데이터 수정 불가능) 

- SERIALIZABLE : 데이터 일관성 및 동시성 위해 MVCC 사용하지 않음

(격리 수준이 올라갈 수록 성능의 저하가 발생할 수도 있음) 

 

 

[Propogation 전파옵션]

@Transactional 이 관리하는 트랜잭션의 범위

예, 트랜잭션 동작 도중 다른 트랜잭션을 호출하는 상황에 대한 선택 (롤백)

 

[출처] 김영한 JPA DB - 내부트랜잭션의 'readonly' 설정

- 전파 옵션에 따라, 부모 트랜잭션 아래 하위 트랜잭션에서 커밋/롤백 호출의 범위가 달라짐 

 

 

4. 락

DB의 락은 '공유자원' 즉, 레코드 에 락을 걸음

- 낙관적 락

[출처] 당뚱로그

데이터에 락을 걸지 않고 진행함

트랜잭션의 커밋과정에서 버전을 확인하고, 같지 않으면 불일치되어 트랜잭션이 롤백됨 

트랜잭션을 필요로 하지 않음 

 

- 비관적 락 

트랜잭션은 충돌이 일어날 것이다 라는 가정하에 Lock을 걸음

조회할 때에는 s-Lock을 획득 -> 수정할 때는 x-Lock을 획득함 

x-Lock이 일어날 때는 자원에 대한 락이 반납될때까지 기다려야 함 

 

[SELECT 는 트랜잭션으로 처리되는가?]
- 트랜잭션이 필요하지 않음
- 하지만 락을 걸어야 하는 경우에는 트랜잭션 처리됨 

[SELECT 절이 LOCK 이 걸리는 경우]
- SELECT ... FOR UPDATE (쓰기 락, Exclusive Lock) : 트랜잭션이 데이터를 읽으면서 다른 트랜잭션이 수정하지 못하도록 함 
- SELECT ... LOCK IN SHARE MODE (공유 락, Shared Lock) : 다른 트랜잭션이 데이터를 읽을 수는 있으나 수정을 못하도록 막음

 

5. 대표적인 락 오류들

- 블로킹

한 트랜잭션이 시작되어 락을 점유하고 있는 상태에서, 같은 자원에 대해 또 다른 트랜잭션 요청이 온 경우 

Lock들의 경합이 발생하여 프로세스가 작업이 진행되지 않고 멈춘 상태를 말함 

 

 

- 교착상태  (=데드락)

더티체킹 (READ UNCOMITTED) 상태에서 공유락이 맞물리면 각자가 배타락을 요구하면서 생기는 경우 

https://vladmihalcea.com/database-deadlock/

1) GOD(리로스1)을 업데이트 하는 트랜잭션1이 수행된다. 

2) 그 사이에 GOD_ITM(리로스2) 를 업데이트 하는 트랜잭션2가 수행된다. 

! 서로의 트랜잭션은 공유 자원에 대해 아직 락을 반납하지 않았다 ! 

3) 트랜잭션1 은 GOD_ITM 을 위해  배타락을 요구한다.

4) 트랜잭션 2는 GOD를 업데이트 하기 위해 배타락을 요구한다. 

 

 

 

4. JPA 트랜잭션 처리 

[JPA repository]

- JPA 사용 시 기본적인 메서드 사용 시에는 내부 코드에서 Transactional이 사용

- 클래스 레벨에서 이미 @Transactional(readOnly=true)가 선언

[출처] lavine.log

 

[JPA 의 영속성 컨텍스트]

- 쿼리가 실행되는 시점

 

 

 

 

 


참고 문헌

- JPA 

https://tech.kakaopay.com/post/jpa-transactional-bri/

 

JPA Transactional 잘 알고 쓰고 계신가요? | 카카오페이 기술 블로그

JPA Transactional과 그에 따른 DB 쿼리 성능과의 관계에 대해서 설명합니다.

tech.kakaopay.com

https://velog.io/@mnetna/JPA%EC%9D%98-%EC%98%81%EC%86%8D%EC%84%B1-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8%EB%9E%80

 

JPA 영속성 컨텍스트란?

들어가기에 앞서 JPA의 영속성 컨텍스트에 대해 공부한 내용을 정리해보고자 한다.JPA는 사용하기 쉬운 만큼 알아야 할 내용도 무궁무진하다.동작 원리를 정확하게는 아니지만 대강적으로 이해

velog.io

https://goalinnext.tistory.com/118

 

JPA 영속성 전이 정리 - (영속성 컨텍스트 및 엔티티 생명주기, 영속성 전이 옵션과 insertable=false, u

안녕하세요. 이번 게시글에선 JPA 영속성 전이에 대해 분석해보고특히 복합키로 구성된 DB구조에서 어떻게 영속성 전이를 처리할지 알아보겠습니다.  “영속성 콘텍스트”는 무엇일까요?영속

goalinnext.tistory.com

 

 

- 스프링 트랜잭셔널

https://joojimin.tistory.com/25

 

Spring Transactional 어디까지 알고있니?

[Spring] @Transactional 트랜잭션이란? 2개 이상의 쿼리를 하나의 커넥션으로 묶어 DB에 전송하고, 이 과정에서 에러가 발생할 경우 자동으로 모든 과정을 원래대로 되돌려 놓는다. 하나 이상의 쿼리를

joojimin.tistory.com

https://sjh9708.tistory.com/243

 

[Spring Boot] 트랜잭션 범위와 전파 속성(Propagation)

트랜잭션은 작업에서 예외가 발생할 경우 Rollback 처리를, 모두 성공할 경우 Commit 처리하는 실행 단위이다.Spring에서는 트랜잭션과 관련된 기술들을 제공하며, 주로 @Transactional 어노테이

sjh9708.tistory.com

 

- DB 커넥션

https://shuu.tistory.com/130

 

커넥션 풀이란 (Connection Pool)

1) 커넥션 풀 (Connection Pool) (1) 커넥션 풀이란 JDBC API를 사용하여 데이터베이스와 연결하기 위해 Connection 객체를 생성하는 작업은 비용이 굉장히 많이 드는 작업 중 하나이다. Connection 객체를 생성

shuu.tistory.com