본문 바로가기
JPA/ORM 표준 JPA

Atomic Query 작성

by clearinging 2022. 4. 28.
반응형

Atomic Query

정의

  • isolation에서 serializable을 사용해 where 절 조건과 index 자체에 lock을 걸지 않는 이상 write누락 이슈가 발생합니다
  • Atomic Query는 Table내부 Data를 update하는 작업에서 기존 데이터를 이용해서 변경하는 것을 의미 합니다

예시

  • 일반 update query
update from food 
set number_of_likes = 10 # 기존 number_of_likes : 9
where food_id = 15;
  • Atomic Query
update from food 
set number_of_likes = number_of_likes + 1
where food_id = 15;
  • 위 결과는 동일하게 number_of_likes의 값이 10으로 변경이됩니다.
  • 하지만 많은 사용자 (2명 이상)가 동이라한 쿼리를 호추라게 되면 어떻게 될까요?

문제 상황 비즈니스 로직

  1. food_id가 15번인 row 검색
  2. 조회한 데이터에서 number_of_likes 값을 1을 더한다
  3. update query를 이용해서 number_of_likes값을 변경한다

cf) 원래 프로젝트에서는 중간에 여러 로직처리가 있지만 문제 상황이 발생하는 것과 별개 이므로 생략 했습니다

테스트 결과

10명 사용자 동시 접근
예상 결과: 20

  1. 일반 update: 12
  2. atomic update: 20

이유

  1. 장점: atmoic query를 이용할 경우 1개의 query에서 number_of_likes를 가져와서 1을 증가시키고 update 를 하게 됩니다. 결론적으로 query가 2개로 나눠져 있지 않기 때문에 동시성 이슈가 해결될 수 있습니다
  2. 단점: JPA/QueryDSL를 사용할 경우 JPQL로 바로 query가 나가기 때문에 영속성 Context를 무시하고 Query수합니다. 그러므로 이전에 영속성 context정보와 DB정보가 불일치 날 수 있기 때문에 flush, clear를 호출해서 영속성 context에 변경 정보를 DB에 미리 넣고 jpql이후에 clear를 통해서 영속성 context정보를 준영속성형태로 변경하는 작업이 필요 합니다
  3. Flush/Clear호출 방식
  • Spring Data JPA에서는 @Modifying를 붙일경우 조회 query를 호출하지 않고, update/inser query를 생성하는 method가 호출하게 됩니다. 그리고 clear/flush를 호출할 수 있도록 기능을 제공해줍니다. 하지만 QueryDSL에서는 @Modifying을 사용하지 못하기 때문에 한계가 있었습니다.
  • 이문제를 해결하기 위해서 @ModifyingQuery라는 Annotation을 생성하고, AOP를 설정해서 SpringDataJPA @Modifying와 동일한 기능으로 동작할 수 있도록 구현해서 문제를 해결하였습니다

https://github.com/YAPP-19th/Android-Team-2-Backend/commit/2123d83cb952e4728700a7339121c8c37632e117

 

feat: flush clear 기능 annotation 기반 AOP로 전환 · YAPP-19th/Android-Team-2-Backend@2123d83

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

github.com

 

반응형

'JPA > ORM 표준 JPA' 카테고리의 다른 글

Fetch Join 별칭 이슈  (2) 2022.01.22
06 연관관계 Mapping 종류  (2) 2021.08.21
05 연관관계  (0) 2021.07.28
04 Entity  (3) 2021.07.08
03. 영속성  (0) 2021.06.30