← 전체 글로 돌아가기

웹 개발

트랜잭션 처리는 배포할 때 처음 의심해야 할 곳

로컬에선 잘 작동하던 DB 트랜잭션이 운영 환경에서 갑자기 실패하는 경험. 그때마다 확인해야 할 것들을 정리했다.

로컬과 운영의 트랜잭션은 다르게 동작한다

로컬 테스트에서 트랜잭션 처리가 완벽해 보였는데 배포 후에 데이터 일관성 문제가 터지는 일이 종종 있다. 대개 설정 차이가 원인이다. 격리 수준(isolation level), 자동 커밋 설정, 커넥션 풀 동작이 환경마다 다르기 때문이다.

먼저 확인할 것들

배포 환경에서 트랜잭션 문제가 의심될 때는 화면 에러만 보지 말고 다음 세 가지를 동시에 기록한다.

  1. 재현 조건: 어떤 동작을 했을 때 문제가 발생하는가
  2. 로그: 데이터베이스 로그에 롤백 기록은 있는가
  3. 응답 상태: API 응답 코드와 메시지는 무엇인가

이 세 가지만 정확히 기록해도 다음 단계를 정하기가 훨씬 쉬워진다.

설정부터 점검한다

가장 먼저 볼 것은 데이터베이스 연결 설정이다.

# 격리 수준 확인 (PostgreSQL 예)
SHOW transaction_isolation;

# 자동 커밋 상태
SHOW autocommit;

# 현재 활성 트랜잭션
SELECT * FROM pg_stat_activity;

로컬에서는 기본값으로 동작하던 것이 운영에선 명시적으로 설정되어 있을 수 있다. ORM 설정에서 자동 커밋을 false로 했는지, 격리 수준을 READ_COMMITTED가 아닌 다른 것으로 했는지 확인한다.

커넥션 풀 확인

멀티스레드 환경에서는 커넥션 풀의 동시성 설정도 중요하다.

# 활성 커넥션 개수 확인
SHOW max_connections;
SELECT count(*) FROM pg_stat_activity;

로컬에선 커넥션이 5개면 충분해도 운영에선 50개 이상이 필요할 수 있다. 풀이 부족하면 타이밍에 따라 트랜잭션이 대기 상태에 빠질 수 있다.

실제 쿼리 흐름 확인

ORM이 예상과 다른 순서로 쿼리를 실행할 수 있다. 실제 데이터베이스 로그를 봐야 한다.

# PostgreSQL 슬로우 쿼리 로그 활성화
SET log_min_duration_statement = 1000; -- 1초 이상

문제가 발생한 시간대의 로그를 보면서, INSERT/UPDATE 순서가 올바른지, 예상치 못한 대기가 있는지 확인한다.

마지막 확인

문제를 수정한 후에는 세 가지를 다시 확인한다.

  1. 같은 조건에서 증상이 재현되지 않는가
  2. 로그에서 바뀐 부분을 한두 줄로 설명할 수 있는가
  3. 실제 운영 데이터로 몇 번 반복해서 성공했는가

이 세 가지가 모두 만족되면 문제 해결이 완료다. 관련 설정 변경 사항을 기록해 두면 비슷한 문제가 나올 때 빠르게 진단할 수 있다.