운영중에 Node.js 모듈이 간혈적으로 갑자기 기능이 동작되지 않는 이슈가 있었습니다.
가장 처음에는 트랜잭션 자체가 동작되지 않아, 로그를 살펴보니 위와같은 내용이 있었습니다. 이게 왜 발생했을까요?
Node.js 에서 ConnectionAcquireTimeoutError 이 발생했는데, 이유를 알 수 없었습니다.
에러 메세지에 대한 원인을 찾아보니, Transaction 이 ConnectionPool 을 물고 있고, graphql에서 새롭게 만들 트랜잭션이 없어서 발생한 문제점이라는 사실을 알았습니다.
최근에 const transaction = await sequelize.transaction(); 관련된 작업이 있었고, 그곳에서 transaction 이 정상적으로 종료되지 않았음을 알 수 눈치챌 수 있었습니다.
그럼 왜 트랜잭션이 정상적으로 종료되지 않았을까?
public async confirm(preOrder: PreOrder) {
try {
const transaction = await sequelize.transaction();
await throwAlreadyAppliedError();
transaction.commit();
return "ok";
} catch (e) {
if (e.message === ALREADY_APPLIED){
// 트랜잭션이 정상적으로 종료되지 않음.
}
else {
transaction.rollback();
}
throw e
}
}
위 코드를 살펴보면, ALREADY_APPLIED 타입의 에러 발생 시 transaction 은 정상적으로 종료되지 않은 상태로 남겨됩니다.
명확히 transaction.rollback(); 또는 transaction.commit(); 을 해야만 합니다. graphQL 에서는 관리하는 트랜잭션과, 관리하지 않는 트랜잭션이 있는데, `const transaction = await sequelize.transaction();` 는 관리하는 트랜잭션에 속하고, 자세한 내용은 해당 문서를 참조해주세요.
그렇게 하지 않을 경우, PostgresSQL의 경우 Idle in transaction 상태로 남겨 됩니다.
해결방법으로는 2가지가 있습니다.
- transaction 코드을 점검한다.
- 트랜잭션 범위를 줄일 수 있도록 한다.
- transaction 이 정상적으로 종료될 수 있도록 코드를 변경한다.
- postgresql에는 Idle in transaction이 일정 기간동안 유지되면 자동으로 이 transaction을 Kill 하는 속성을 추가합니다.
다음 포스팅에서는 Idle in transaction 에 대한 내용을 다뤄볼까 합니다.
[참고자료]
'개발 관련됨 > 개발 이슈를 해결함' 카테고리의 다른 글
Java Regex 정규표현식 사용시 java.lang.StackOverflowError 가 발생하는걸까 (0) | 2023.02.25 |
---|---|
비관적 잠금, 낙관적 잠금 그런 동시성 이슈 해결하기 (0) | 2023.01.11 |
Message Relay 를 PollingPublisher 방식으로 구현하기 (2) | 2022.06.19 |
정규표현식에서 알지 못했던 capture group 과 non- capture group (0) | 2022.06.06 |
Springboot 에서 react.js 연동시 모든 view 맵핑을 index.html으로 forwarding 하는 방법은? (2) | 2022.04.26 |
댓글