최근 nestjs와 typeorm, RDBMS인 mysql을 통해서 트랜잭션 기능을 활용하던 중에 올바른 트랜잭션을 사용하지 못했던 케이스가 있었다.
트랜잭션의 connection의 문제.
대략적인 상황의 코드를 예시로 들자면
async method() {
const queryRunner = this dataSource.createQueryRunner()
await queryRunner.startTransaction()
const temp = await queryRunner.manager.findOne(
Repository,
{
select: ['column1', 'columnn2'],
where: {
column3: ...
}
}
).then( res => {
return res.data
} )
try {
...
} catch(err) {
...
await queryRunner.rollbackTransaction()
} finally {
await queryRunner.release()
}
}
위 코드의 문제점은 temp에서 then을 사용한 후 return을 하게되면 트랜잭션은(transaction connection) 끝나지 않았지만 return으로 인해 메소드는 끝난 상태
라는것.
그러면 DB의 connection은 끝나지 않은 상태에서 계속 적치되고 결국은 우리가 흔히들 얘기하는 '뻑이 났다.'라는 경우가 발생하게 된다.
여기서 챙겨야 할 것.
- DB connection이 적치가 발생하지 않도록 하기위해서는 트랜잭션 시작시에 가능하면 바로 try문을 사용할 수 있는 팁.
- then함수와 같은 하나의 쿼리작동에서 추가적인 리턴이 발생하지 않도록 인지하는 팁
- 트랜잭션의 적절한 사용위치 파악의 팁
- queryRunner와 dataSource의 적절한 사용의 팁
(만약, temp 영역을 queryRuuner.managet.findOne에서 queryRunner가 아닌 dataSource를 사용하거나 try안에 넣어준다.)
정도이다. 결국 챙겨야할 것의 논점은 바로 트랜잭션의 적절한 사용
이다.
위와같은 경우가 발생했다고 할 때, mysql 의 쿼리문을 참고하면
--DB 설정 값 확인 방법(커넥션 최대값 => max_connections)
$ show variables;
--커넥션 최대값 변경 (해당 DB 튜닝은 우선적으로는 지양. XX는 커넥션 임의의 수)
$ set global max_connections = XX;
--현재 연결된 커넥션 갯수 조회(Thread_connected)
$ show status;
--현재 연결된 커넥션 목록 조회
$ show processlist;
--연결되어있는 커넥션 끊기(kill 커넥션의 ID)
$ kill xxx
```.
이정도로 정리해볼 수 있을것 같다