개발일기장
SQLSessionManager.newInstance()에서 어떤 순서로 Connection을 가지고 오고 반환하는가. 본문
아니 Copilot은 무적인가? 그냥 대충 말해도 찰떡같이 말하고 순서도를 그려주는 코드를 작성해준다. 이렇게까지 해주는데 내가 공부를 할 필요가 있을까 생각이 든다.
1. newInstance()시점
평소에 소스코드만 보고 설정값은 안봤는데 여기서 Transaction에서 순서가 끊어짐을 느꼈다.
분명 DataSource에서 connection은 가지고 오는데 남는것은 session만 있는게 아닌가? 그래서 하나씩 끼워맞추면서 이해는 했는데 이부분 정리가 필요한 것 같다.
SqlSessionManager에서 Connection을 가지고 오는 순서도를 그려달라고 했다.
일단 여기까지는 문제가 없다. 문제는 getConnection부분이다.
build나 create같은거는 application 시작 시점에 그대로 설정을 해주고,
소스코드에서 따로 getConnection()을 해주지 않고 그냥 newInstance()랑 openSession()까지만 툭 던지면 끝이다.
요부분을 어떻게 이해를 해야할까
build()시점에 properties(xml)를 읽어서 그냥 넣어준다. 거기에 DataSource와 관련된 설정값이 포함되어 있다.
이부분을 작성해달라고 하면 아래와 같다
1. 프로퍼티 파일 (database.properties)
프로퍼티 파일에서 데이터베이스 연결 정보를 설정합니다:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb
username=root
password=password
2. SqlSessionFactory 설정 (Java 코드)
Java 코드에서 SqlSessionFactory를 설정할 때, DataSource를 주입받아 설정합니다:
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.io.Resources;
import java.io.Reader;
import java.util.Properties;
public class MyBatisConfig {
public SqlSessionFactory sqlSessionFactory() throws Exception {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
Properties properties = new Properties();
properties.load(Resources.getResourceAsReader("database.properties"));
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
return builder.build(reader, properties);
}
}
여기까지도 정리하니 이해가 간다.
newInstance를 통해 session을 생성 할 때에도 예외처리가 안되거 있거나 경합발생시 어떻게 되는지 물어보자.
1. borrowObject에서 예외처리를 안하는 경우 newInstance까지 Exception이 전파가 되는지?
> 이부분은 소스코드 다시 보고 직접 Local에서 테스트 해볼 수 있을 것 같다.
2. 경합이 발생할 가능성에 대해서
SqlSessionManager.newInstance()로 세션을 생성할 때, DataSource와 ConnectionPool에서 경합이 발생할 가능성은 있습니다. 특히, 여러 스레드가 동시에 세션을 생성하려고 할 때 경합이 발생할 수 있습니다. 이러한 경합은 성능 저하나 데드락과 같은 문제를 일으킬 수 있습니다.
경합 발생 가능성
- Connection Pool: 여러 스레드가 동시에 ConnectionPool에서 Connection을 빌리려고 할 때 경합이 발생할 수 있습니다.
- DataSource: DataSource가 스레드 안전하지 않다면, 여러 스레드가 동시에 DataSource에 접근할 때 경합이 발생할 수 있습니다.
GenericObjectPool은 스레드 안전성을 제공하도록 설계되었습니다. 이는 여러 스레드가 동시에 borrowObject와 returnObject 메서드를 호출할 수 있도록 하기 위해 내부적으로 동기화 메커니즘을 사용합니다. 따라서, 기본적으로 GenericObjectPool은 스레드 안전합니다.
스레드 안전성
- 동기화 메커니즘: GenericObjectPool은 내부적으로 동기화 메커니즘을 사용하여 여러 스레드가 동시에 접근할 때 발생할 수 있는 문제를 방지합니다.
- 스레드 안전한 메서드: borrowObject와 returnObject 메서드는 스레드 안전하게 구현되어 있습니다.
이렇게 답변을 해준다.
일단 Custom된 영역에서 문제가 발생하는게 아닌지 로그찍고 예외처리 로직도 추가해봐야할 것 같다.
2. close()시점
session을 close할 때에는 아래가 올바른 순서이다.
근대 여기서 close의 순서가 달라지면 문제가 발생할 수 있을것 같다. 그부분에 대하여 물어보자
순서의 중요성
- Connection 반환: 세션을 닫을 때 가장 중요한 것은 사용한 Connection을 적절히 반환하는 것입니다. 이를 통해 연결 풀이 안정적으로 유지됩니다.
- 정리 작업: 세션을 닫기 전에 필요한 정리 작업을 수행해야 합니다. 예를 들어, 트랜잭션을 커밋하거나 롤백하는 작업이 필요할 수 있습니다.
- 리소스 해제: 세션을 닫을 때 모든 리소스를 적절히 해제해야 합니다. 이를 통해 메모리 누수를 방지할 수 있습니다.
문제 발생 가능성
- 트랜잭션 정리 누락: 트랜잭션을 커밋하거나 롤백하지 않으면 데이터베이스 상태가 불안정해질 수 있습니다.
- Connection 반환 누락: Connection을 반환하지 않으면 연결 풀이 고갈될 수 있습니다.
- 정리 작업 누락: 필요한 정리 작업을 수행하지 않으면 리소스 누수나 성능 저하가 발생할 수 있습니다.
이렇다고 한다. 뭔가 이부분도 확인을 해봐야할 것 같다.
비정상적으로 transaction이 종료되었을 때에 강제적으로 close를 하는 로직이 여기저기 들어있었던 기억이 난다.
그러면 session 을 먼저 close()하지 않고 Connection 을 먼저 닫거나 Connection Pool에 반환을 하는 경우 어캐 되는지 물어보자
발생 가능한 문제
- 트랜잭션 관리 문제:
- SqlSession이 트랜잭션을 관리하고 있는 경우, Connection을 반환하기 전에 트랜잭션을 커밋하거나 롤백해야 합니다.
- Connection을 먼저 반환하면 트랜잭션이 제대로 커밋되지 않거나 롤백되지 않을 수 있습니다.
- 리소스 누수:
- SqlSession이 여전히 Connection을 참조하고 있는 상태에서 Connection을 반환하면, SqlSession이 더 이상 유효하지 않은 Connection을 참조하게 됩니다.
- 이는 리소스 누수로 이어질 수 있으며, 연결 풀의 상태를 불안정하게 만들 수 있습니다.
- 데이터 일관성 문제:
- SqlSession이 닫히기 전에 Connection을 반환하면, 데이터베이스 작업이 중간에 끊길 수 있습니다.
- 이는 데이터 일관성 문제를 야기할 수 있습니다.
이렇단다.. local에서 테스트 해보면 될것 같다. session 을 닫기전에 먼저 connection 을 지워버린다던지 하는 방식으로..
근본적인 문제를 잡지 않고 수면 위에만 봐서 문제를 확인할 수 없었던거같은데 점점 뭔가 답이 나올것 같은 생각이 든다.
'JAVA' 카테고리의 다른 글
Connection 을 왜 더 이상 끌어오지 못하는 걸까 (GenericObjectPool) (1) | 2024.09.16 |
---|---|
CGLIB proxy ... (1) | 2023.11.26 |
Proxy ... (1) | 2023.11.26 |
Reflection ... (0) | 2023.11.26 |
Java 데이터 접근 기술 - transaction & exception(Check,UnCheck) (3) (0) | 2023.02.08 |