Spring JpaItemPagingReader row update시 reader 누락 문제
June 1, 2023 • ☕️ 2 min read
문제상황
예시) 온보딩 챌린지 발행을 위한 대상 유저 Reader
- JpaPagingItemReader에서 chuck 갯수로 잘라서 Sql문 실행 결과 Process
- Write 대상 테이블에 Insert
- 동일한 sql문 실행시 이전 청크 write insert로 인해 작업 완료된 row는 검색되지 않음.
- JpaPagingItemReader는 offset과 page를 갖고있음.
- 따라서 실행된 row 수 만큼 누락 문제 발생.
대표적인 ItemReader
1. ItemReader
: 처리하는 데이터를 모두 메모리에 불러와 저장하고, chuck 단위로 process를 진행.
2. Database Reader
- Cursor 기반 ItemReader 구현체
: Database에서 데이터를 Streaming ( ex. literator, next() )
(JpaCursorItemReader의 경우 데이터를 DB에서 모두 읽고 서비스 인스턴스에서 직접 Iterator로 cursor로 동작하는 것처럼 흉내 내는 방식)
(할거면 JdbcCursorItemReader 혹은 HibernateCursorItemReader를 사용 다만
“ Cursor는 하나의 Connection으로 Batch가 끝날때까지 사용되기 때문에 Batch가 끝나기전에 Database와 어플리케이션의 Connection이 먼저 끊어질수 있습니다. “)
- Paging 기반 ItemReader 구현체
: 페이지 단위로 한번에 데이터를 조회 (page, offset ..)
(Chuck마다 새로 select)
해결방법
1. Cursor Item Reader 사용
: 데이터를 모두 읽은 상태에서 차례대로 가져오기 때문에 데이터의 변경사항이 적용되지 않음.
2. JpaPagingItemReader에서 page를 무조건 0으로 override
: 변경사항이 반영된 row는 빠지고 신규 row들만 select
3. ZeroOffsetItemReader 기반
: pk id로 order by를 한 뒤 offset은 항상 0, 읽었던 마지막 id값을 기억해 그 이후부터 실행.
: MySql에서 예를들어 offset이 10000, limit가 50인 경우. 실제로는 10050row를 select 한 뒤 10000 row를 버리는 방식이라 성능에 문제가 있음. 이것을 개선하기 위해 만들어진 reader
관련 문서
https://jojoldu.tistory.com/336
https://jojoldu.tistory.com/337
https://tech.kakaopay.com/post/ifkakao2022-batch-performance-read/#zerooffsetitemreader
https://jojoldu.tistory.com/528
https://www.eversql.com/faster-pagination-in-mysql-why-order-by-with-limit-and-offset-is-slow/