일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- fast api
- 쿠버네티스
- kubernetes
- BFS
- 오픈시프트
- vue.js
- 솔루션조사
- GPT
- 생성형 AI
- LeetCode
- vuejs
- 도커
- fastapi
- 리트코드
- OpenShift
- SpringBoot
- LLaMa
- 로깅
- POD
- Redis
- Machine Learning
- 머신러닝
- Python
- 생성형
- jpa
- 컨설팅
- 컨설턴트
- k8s
- 메세지큐
- Docker
- Today
- Total
수 많은 우문은 현답을 만든다
@Transactional 과 DB Connection 반환 이슈 본문
안녕하세요 조영호입니다.
오늘은 Transational 어노테이션을 사용하면서 발생했던 한 가지 문제에 대해서 공유하고자 합니다.
@Transactional 이 선언된 하나의 메소드에서 내부적으로 3개의 메소드를 호출하고 있는 메소드에서 아래 오류가 발생했습니다.
오류내용
- Error enlisting in transaction - connection might be broken? Please check the logs for more information...
- nested exception is org.apache.ibatis.executor.ExecutorException: Error preparing statement: the XA resource has become unavailable
서비스를 운영하다보니 자꾸 Database Connection이 끊기는 문제가 발생했고, 처음에는 Network나 Database의 문제가 아닐까 생각했습니다. 그러나 모니터링 결과 Network나 Database 단의 순단이나 오류 로그는 따로 없었습니다.
분석
소스코드 분석
1. @Transactional이 적용된 메소드는 public인가?
@Transactional 어노테이션은 기본적으로 public 메소드에 적용됩니다. 스프링은 프록시 패턴을 사용하여 트랜잭션 처리를 구현하는데, 이를 위해 public 메소드에 대해서만 프록시를 생성합니다. public에 대해서만 프록시를 생성하는 이유는 외부에서 객체에 접근할 때 추가적인 로직을 수행하기 위해서입니다. 자식 메소드까지 모두 public일 필요는 없습니다.
2. 자식 메소드들에도 @Transactional이 선언되어있는가?
부모 메소드에 @Transactional 어노테이션이 선언되어있으면 내부 메소드들은 모두 하나의 트랜잭션으로 묶입니다.
3. Rollback이 제대로 되었는가?
@Transactional 어노테이션은 Unchecked Exception(Runtime Exception) 에서만 Rollback이 발생합니다.
=> 코드상에 IOException(Checked Exception) 예외를 던지는 곳이 있었는데, 이 경우 @Transactional은 롤백을 수행하지 않기 때문에 커넥션이 정상적으로 반환되지 않고 유지 됩니다 (누수 발견)
4. 커넥션 수는 적절한가?
기본 권장사항인 max-pool-size : 10을 쓰고있었는데, 커넥션 수에 따른 성능을 찾아보다가 좋은 포스트를 보고 아래와 같이 조정했다.
max-pool-size : 10 -> 32+1 (인프라 접근 권한이 없어 Disk 스펙은 알 수 없어서 여유롭게 50으로 설정)
결과
아직 8시간정도 지나면 mysql 접속이 끊기는 오류는 동일하다..
application.yml을 자세히 보니 아래와같이 작성되어있었다.
env.datasource.dbname.props.jdbc-url = ~&autoReconnect=true
음 과연 이렇게 하면 autoReconnect 옵션이 재대로 작동할까?
원칙적으로는 spring.datasource.dbname.jdbc-url 에다가 작성을 해줘야한다. 내 판단으로는 동료가 설정한 위와같은 옵션은 custom 설정이기 때문에 autoRecoonect가 되지 않은것같았다.
그래서 아래와같이 Datasource 빈을 생성할때 명시적으로 옵션을 넣어주었다.
@Bean
public DataSource dataSource(@Qualifier("dataSourceProperty") DataSourceProperty dataSourceProperty) {
Properties property = new Properties();
property.setProperty("url", dataSourceProperty.getProps().getJdbcUrl() + "&autoReconnect=true");
결과는 내일 아침에 다시 본다..
'개발지식 > Springboot' 카테고리의 다른 글
설정파일 불러오기 @Value @ConfigurationProperties (0) | 2022.12.23 |
---|---|
한글이 깨질때 (0) | 2022.07.27 |
세마포어(Semaphore) (0) | 2022.07.13 |
FK 를 쓰지 않는 이유 (0) | 2022.03.21 |
예외처리에 대한 고찰 - 3편 (성능 개선) (0) | 2022.03.09 |