콘텐츠로 이동

읽기 전용 트랜잭션

읽기 전용 트랜잭션(Read-Only Transaction)은 데이터베이스의 데이터를 수정(INSERT, UPDATE, DELETE)하지 않고 오직 조회(SELECT)만 수행하겠다고 명시하는 트랜잭션 모드입니다.

1. 읽기 전용 트랜잭션의 주요 목적

성능 최적화 (Performance)

  • 스냅샷 관리: MySQL(InnoDB) 같은 엔진에서는 읽기 전용 트랜잭션에 대해 트랜잭션 ID를 할당하지 않거나, 읽기 전용 상태임을 인지하여 내부적인 오버헤드를 줄입니다.
  • 리소스 절약: 변경 사항을 기록하는 Undo 로그나 리두 로그(Redo Log) 생성을 최소화하여 시스템 부하를 줄입니다.

데이터 정합성 (Consistency)

  • 선택적 격리 수준: 트랜잭션 내에서 여러 번의 조회를 수행할 때, 그 사이에 다른 사용자가 데이터를 수정하더라도 동일한 결과(Snapshot)를 보장받을 수 있습니다.

2. DB 엔진별 동작 원리

각 데이터베이스 관리 시스템(DBMS)은 읽기 전용 트랜잭션을 처리하는 방식이 조금씩 다릅니다.

DBMS 주요 동작 특징
MySQL (InnoDB) START TRANSACTION READ ONLY 명령 사용 시, 읽기 전용 트랜잭션으로 간주되어 Read-Write 트랜잭션보다 가벼운 구조로 관리됩니다.
Oracle SET TRANSACTION READ ONLY를 사용하면 트랜잭션이 시작된 시점의 SCN(System Change Number)을 기준으로 데이터를 조회하여 일관된 읽기를 보장합니다.
PostgreSQL SET TRANSACTION READ ONLY 설정 시, 해당 트랜잭션 내에서 데이터를 변경하려는 시도가 발생하면 즉시 에러를 발생시켜 실수를 방지합니다.

3. 애플리케이션 레벨에서의 활용 (Spring Framework)

Java 진영의 Spring 프레임워크에서는 @Transactional(readOnly = true) 어노테이션을 통해 이를 매우 쉽게 적용할 수 있습니다.

Spring + Hibernate 조합 시 이점

  1. Dirty Checking 생략: Hibernate는 엔티티의 상태 변화를 감지하기 위해 스냅샷을 보관하는데, readOnly = true로 설정하면 이 과정을 생략하여 메모리와 CPU 사용량을 줄입니다.
  2. Flush 모드 설정: Flush 모드를 MANUAL로 설정하여, 실수로 데이터가 변경되더라도 DB에 반영되지 않도록 보호합니다.
  3. DB 부하 분산 (Replication): DB가 Master-Slave(Source-Replica) 구조로 구성되어 있을 때, 읽기 전용 트랜잭션은 자동으로 Slave DB로 연결되도록 설정하여 Master DB의 부하를 분산할 수 있습니다.

4. 주의사항

  • 진짜 읽기만 하는가?: readOnly = true 설정 후 내부 로직에서 update 쿼리를 실행하면 예외가 발생하거나, DB 설정에 따라 무시될 수 있으므로 주의해야 합니다.
  • 커넥션 점유: 아무리 가벼운 읽기 트랜잭션이라도 트랜잭션 범위가 너무 길어지면 커넥션 풀(Connection Pool)의 점유 시간이 늘어나 시스템 전체의 병목 현상을 초래할 수 있습니다.

결론

데이터의 변경이 없는 단순 조회 서비스나 API라면 readOnly = true를 기본으로 사용하는 것이 성능과 안정성 면에서 권장되는 관례(Best Practice)입니다.