본문 바로가기
개발 관련됨/개발 이슈를 해결함

ConnectionAcquireTimeoutError [SequelizeConnectionAcquireTimeoutError] 문제 해결하기

by simplify-len 2022. 9. 11.

운영중에 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가지가 있습니다.

  1. transaction 코드을 점검한다.
    • 트랜잭션 범위를 줄일 수 있도록 한다.
    • transaction 이 정상적으로 종료될 수 있도록 코드를 변경한다.
  2. postgresql에는 Idle in transaction이 일정 기간동안 유지되면 자동으로 이 transaction을 Kill 하는 속성을 추가합니다.

다음 포스팅에서는 Idle in transaction 에 대한 내용을 다뤄볼까 합니다.

[참고자료]

댓글