(ORA-01555, ORA-01652, ORA-04031)

오라클 데이터베이스(Oracle DB)를 운영하거나 대용량 쿼리를 튜닝하다 보면 기습적으로 마주치는 무서운 에러들이 있습니다. 대표적으로 ORA-01555(Snapshot too old), ORA-01652(Unable to extend temp), ORA-04031(Unable to allocate shared memory)이 그렇습니다.
많은 개발자분들이 이 에러들을 마주했을 때 "DB 부하가 심한가 보네, CPU나 메모리를 늘려야 하나?"라고 막연하게 생각하곤 합니다. 하지만 이 에러들은 각각 발생하는 영역과 원인이 완전히 다릅니다.
오늘은 오라클의 양대 메모리 축인 SGA와 PGA의 차이를 알아보고, 이를 바탕으로 오라클 3대 에러의 작동 원리와 해결법을 완벽하게 정리해 보겠습니다.


1. 오라클 메모리의 양대 산맥: SGA vs PGA

오라클 메모리는 크게 모든 프로세스가 공유하는 공간과 개별 프로세스가 독점하는 공간으로 나뉩니다.

🏢 SGA (Shared Global Area) : "뷔페 식당의 공용 음식 진열대"

  • 개념: 오라클 인스턴스가 켜질 때 할당되며, 모든 세션과 사용자가 공동으로 사용하는 공유 메모리 공간입니다.
  • 목적: 디스크 I/O를 줄이기 위한 데이터 블록 캐싱, SQL 실행 계획 공유 등 시스템 전반의 성능 최적화를 담당합니다.
  • 핵심 요소: 데이터를 담아두는 Database Buffer Cache, SQL 파싱 정보를 담는 Shared Pool 등이 있습니다.

🍽️ PGA (Program Global Area) : "나만 쓰는 개인 접시와 식탁"

  • 개념: 사용자가 DB에 접속(Connect)할 때마다 개별 세션(프로세스)에 독립적으로 할당되는 비공유 메모리 공간입니다. 다른 사용자는 절대 들여다볼 수 없습니다.
  • 목적: 다른 세션의 방해를 받지 않고 자신만의 쿼리 연산(정렬, 조인 등)을 처리하기 위해 사용합니다.
  • 핵심 요소: 정렬 공간인 Sort Area, 해시 조인을 위한 Hash Area 등이 있습니다.

2. 영역별로 발생하는 오라클 3대 장애 에러 원인 분석

에러 코드 에러 메시지 키워드 주요 발생 영역 에러의 한 줄 요약
ORA-04031 unable to allocate ... bytes of shared memory SGA - Shared Pool "바인드 변수를 안 써서 공유 메모리가 쪼개짐"
ORA-01652 unable to extend temp segment PGA / TEMP Tablespace "내가 정렬을 너무 크게 해서 임시 공간을 다 씀"
ORA-01555 snapshot too old: rollback segment... UNDO Tablespace "남이 데이터를 고쳐서 내 과거 이력이 지워짐"

3. 에러별 딥다이브: 원인과 해결 방법

① ORA-04031 : SGA Shared Pool 파편화 (메모리 이슈)

  • 원인: Shared Pool의 총 용량은 남아있을지 몰라도, 메모리가 잘게 쪼개지는 파편화(Fragmentation)가 발생하여 오라클이 요구하는 연속된 크기의 메모리 덩어리를 할당하지 못할 때 터집니다. 90% 이상은 소스코드에서 바인드 변수(Bind Variable)를 쓰지 않고 리터럴 쿼리를 날려 발생합니다.
  • 비유: 10인 단체 손님이 왔는데 식당에 2인용 테이블만 흩어져 있어서 자리를 못 주는 상황.
  • 해결법:
  • 리터럴 쿼리를 바인드 변수(:id 등) 구조로 소스코드 전면 수정 (근본 해결)
    • 임시 조치로 ALTER SYSTEM FLUSH SHARED_POOL; 실행하여 메모리 병합
    • 오라클 SHARED_POOL_SIZE 파라미터 증설

② ORA-01652 : TEMP SPACE 오류 (정렬/조인 부하)

  • 원인: ORDER BY, GROUP BY, HASH JOIN 등 대량의 정렬 연산을 수행할 때, 개인 식탁인 PGA 메모리가 부족해지면 디스크의 TEMP Tablespace를 빌려 씁니다. 하지만 이 TEMP 공간마저 가득 차버리면 쿼리가 멈추며 발생합니다. 에러를 낸 쿼리 본인이 범인인 순수 자원 고갈형 오류입니다.
  • 비유: 내 개인 접시(PGA)가 좁아서 거실 바닥(TEMP)에 음식을 펼쳐놓고 먹다가, 거실 바닥까지 꽉 차서 더 이상 식사를 못하는 상황.
  • 해결법:
  • 쿼리 튜닝을 통해 불필요한 대량 정렬 제거 및 인덱스 활용
    • TEMP Tablespace 물리적 크기 증설
    • PGA 관련 파라미터(PGA_AGGREGATE_TARGET) 상향 조정

③ ORA-01555 : SNAPSHOT TOO OLD (데이터 일관성 이슈)

  • 원인: 긴 조회(Read) 쿼리가 도는 와중에, 다른 세션들이 대량의 변경(DML: UPDATE/DELETE)을 가하고 COMMIT을 할 때 발생합니다. 조회 쿼리는 시작 시점의 과거 데이터를 보여주기 위해 UNDO Tablespace를 찾아가는데, 변경 작업이 너무 많아 오라클이 옛날 Undo 데이터를 새 데이터로 덮어써 버렸기(Overwrite) 때문입니다. 남들 때문에 내가 에러를 맞는 억울한 오류입니다.
  • 비유: 칠판에 적힌 긴 글을 공책에 받아 적고 있는데, 옆 사람이 이미 지나간 앞부분을 지우고 새 글을 써버려서 앞 내용을 다시 확인하지 못하는 상황.
  • 해결법:
  • 가장 중요: 조회 쿼리를 튜닝하여 실행 시간 자체를 단축시키기 (빨리 읽고 끝내기)
    • UNDO Tablespace 크기 증설
    • Undo 데이터 보존 시간을 늘려주는 UNDO_RETENTION 파라미터 상향 조정
    • 변경 작업 시 건건이 Commit(잦은 커밋)하는 패턴 지양하기

마치며: "DB 부하"라는 말 대신 명확하게 소통하자!

앞으로 장애가 발생했을 때 단순히 "DB에 부하가 걸렸다"고 표현하기보다는, 각 에러의 성격에 맞게 소통해 보세요.

  • "바인드 변수 미사용으로 인한 SGA 메모리 파편화입니다." (ORA-04031)
  • "대량 정렬로 인한 TEMP 공간 부족입니다." (ORA-01652)
  • "타 세션의 대량 DML로 인한 UNDO 데이터 보존 한계 초과입니다." (ORA-01555)

원인을 명확히 짚어내야 개발팀과 DBA가 낭비 없이 정확한 해결책(소스 수정 vs 인프라 증설)을 찾을 수 있습니다!

반응형