읽기 전용 트랜잭션
읽기 전용 트랜잭션(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 조합 시 이점¶
- Dirty Checking 생략: Hibernate는 엔티티의 상태 변화를 감지하기 위해 스냅샷을 보관하는데,
readOnly = true로 설정하면 이 과정을 생략하여 메모리와 CPU 사용량을 줄입니다. - Flush 모드 설정: Flush 모드를
MANUAL로 설정하여, 실수로 데이터가 변경되더라도 DB에 반영되지 않도록 보호합니다. - DB 부하 분산 (Replication): DB가 Master-Slave(Source-Replica) 구조로 구성되어 있을 때, 읽기 전용 트랜잭션은 자동으로 Slave DB로 연결되도록 설정하여 Master DB의 부하를 분산할 수 있습니다.
4. 주의사항¶
- 진짜 읽기만 하는가?:
readOnly = true설정 후 내부 로직에서update쿼리를 실행하면 예외가 발생하거나, DB 설정에 따라 무시될 수 있으므로 주의해야 합니다. - 커넥션 점유: 아무리 가벼운 읽기 트랜잭션이라도 트랜잭션 범위가 너무 길어지면 커넥션 풀(Connection Pool)의 점유 시간이 늘어나 시스템 전체의 병목 현상을 초래할 수 있습니다.
결론¶
데이터의 변경이 없는 단순 조회 서비스나 API라면 readOnly = true를 기본으로 사용하는 것이 성능과 안정성 면에서 권장되는 관례(Best Practice)입니다.