관리 메뉴

개발공부기록

Redo Log, Undo Log 본문

스터디/DB

Redo Log, Undo Log

소소한나구리 2025. 5. 11. 20:38
728x90

리두로그(Redo Log), 언두로그(Undo Log)

Redo Log와 Undo Log는 트랜잭션의 ACID 속성을 보장하기 위해 사용되는 기술이다

 

ACID 속성은 데이터베이스 시스템의 신뢰성과 무결성을 위한 기본 요소로 트래잭션이 안정적으로 처리되도록 보장하며 동시에 액세스하는 복잡한 다중 사용자 환경에서도 데이터베이스를 일관되고 안정적이게 예측 가능한 상태로 유지하게 해준다

 

ACID 속성을 유지하면 데이터 무결성을 보장하고 오류를 효과적으로 처리하여 데이터 베이스 시스템을 신뢰성을 보장할 수 있게 해준다.

 

ACID 속성

  • Atomicity(원자성)
    • 트랜잭션에 포함된 데이터의 변경은 전부 OK이거나 모두 NG 라는 'all or nothing'을 말한다
    • 트랜잭션은 더 이상 분리할 수 없는 최소 단위 이므로 수행중인 트랜잭션에서 데이터를 일부만 변경하고 나머지는 수행하지 하지 않은 상태로 커밋할 수 없다.
    • 간단히 계좌 이체를 예를 들면 A 계좌에서 출금하고 B 계좌에 입금했을 때 출금은 기록되었지만 입금은 기록되지 않는 상황은 발생하지 않아야 한다는 뜻이다
  • Consistency(일관성)
    • 트랜잭션에 의해 데이터 간의 일관성이 어긋나서는 안된다는 의미이며 특히 사용자 뷰 관점에서 그렇다고 한다.
    • 예를 들어 고객 개인의 데이터는 변경되었는데 고객 전체 통계 데이터는 변경되지 않는 상황은 발생하지 않아야 한다는 뜻이다.
  • Isolation(고립성)
    • 트랜잭션끼리는 분리되어 각각 독립적이라는 뜻으로 어떤 트랜잭션을 단독으로 실행했거나 다른 트랜잭션과 동시에 실행했더라도 결과는 같아야 한다
    • 고립성을 지키기 위해 synchronization(동기화) 기술을 사용하며 다양한 잠금과 동시성 제어 메커니즘을 활용하게 된다.
    • 고립성이 지켜지지 않는다면 비정상적인 동작이 발생하게 되어 예상할 수 없는 결과가 나타나게 된다
    • 대부분 상용 DBMS는 아래의 레벨을 준수하여 고립 정도를 설정한다
      • Read Uncommitted
      • Read Committed
      • Repeatable Read
      • Serializable
  • Durability(지속성)
    • 성공적으로 수행된 트랜잭션은 영속해야 한다는 뜻으로 커밋한 트랜잭션은 장애가 발생하더라도 데이터가 복구 되어야 한다
    • 커밋된 데이터임에도 시스템 장애로 커밋된 데이터가 완전히 사라지거나 한다면 DB의 신뢰성이 무너지게 된다

 

Redo Log, Undo Log

상용 RDBS 대부분은 ACID를 구현하기 위해 로그를 활용하고 있는데 트랜잭션이 커밋된 후에도 시스템 장애가 발생했을 때 변경 내용을 복구하는 것이 Redo Log(재실행 로그)이고 트랜잭션이 실패하거나 롤백될 경우 변경 이전의 상태로 되돌리는 것이 Undo Log(되돌리기 로그)이다

 

즉 Redo Log는 데이터의 지속성을 보장하기 위해 사용되는 기술이고, Undo Log는 데이터의 원자성과 독립성을 보장하기 위해 사용되는 기술이며 로그를 둘 다 사용하는 이유는 각 로그가 서로를 보완하고 있기 때문이다.

 

Redo Log의 동작 방식

  1. 변경 내용 기록: 트랜잭션이 데이터를 변경하면 해당 변경 내용이 Redo Log Buffer에 기록이 된다.
  2. 로그 파일에 기록: Redo Log Buffer의 내용은 주기적으로 또는 트랜잭션 커밋 시 Redo Log 파일에 기록이 된다.
  3. 장애 발생 시 복구: 시스템 장애 발생 후 다시 시작할 때 Redo Log를 사용하여 커밋된 내용을 데이터 파일에 적용한다.

Redo Log는 MySQL 기준으로 데이터 디렉토리의 #innodb_redo 하위 디렉토리에 있는 #ib_redoN 파이들에 저장된다

실제로 나의 local MySQL에서 검색하여 나온 redo log의 데이터들이 엄청나게 많이 저장되어 있었다.

 

 

가장 위에 ib_redo146이 현재 사용중인 RedoLog 파일이며 그 아래 tmp 가 붙은 파일들은 예비 로그 파일들로 아직 사용되지 않았지만 Redo Log 용량을 조정할 때 자동으로 생성된 준비 파일이라고 한다

 

indodb_redo_log_capacity를 조절하면 자동으로 생성된 준비 파일의 개수를 조정할 수 있다고 한다.

 

Redo Log 내부는 LSN(Log Sequence Number) 기준으로 관리되어 순차적으로 기록되며 각 로그 파일은 특정 LSN 범위를 가진다고 한다.

해당 파일들은 순환 구조로 사용되어 오래된 로그는 덮어씌워진다.

 

Redo Log의 설정 변수들은 아래와 같다

  • innodb_redo_log_capacity: 전체 Redo Log의 최대 용량 (ex. 8GB)
  • innodb_log_files_in_group: Redo Log 파일 개수
  • innodb_log_file_size: 파일 당 용량
  • innodb_flush_log_at_trx_commit: 디스크 flush 전략 조절

 

Undo Log 동작 방식

  1. 변경 이전 상태 기록: 트랜잭션이 데이터를 변경하기 전에 변경 이전의 상태를 Undo Log에 기록한다
  2. 롤백 시 복원: 트랜잭션이 롤백 되면 Undo Log를 사용하여 데이터를 변경 이전의 상태로 복원한다
  3. MVCC 지원: 다중 버전 동시성 제어(MVCC)를 위해 Undo Log를 사용하여 트랜잭션이 일관된 데이터를 읽을 수 있도록 지원한다

Undo Log는 기본적으로 Undo Tablespace 내에 Rollback Segment에 저장된다고 한다.

사용자 정의 테이블용 Undo는 일반 Undo 테이블 스페이스에, 임시 테이블용 Undo는 global temporary tablespace에 저장된다.

 

Undo Log의 내부 구성 요소는 아래와 같다

  • Undo Log Record: 변경 전 상태를 저장한 레코드
  • Undo Segment: Undo Record들의 묶음
  • Rollback Segment: 여러 Undo Segment를 보관
  • Undo Tablespace: Rollback Segment 저장소 (128개까지 지원)

MySQL은 트랜잭션당 최대 4개의 Undo Log을 사용한다고 하는데 MySQL의 innoDB 엔진은 Undo Log를 작업 유형에 따라 분리해서 관리하여 성능 최적화와 MVCC, Rollback 처리의 효율성을 위한 설계때문이라고 한다.

 

일반 테이블이냐 임시 테이블이냐에 따라서 달라지고 insert 쿼리이냐 update/delete 쿼리이냐에 따라서 달라지는데, 일반 테이블의 Log는 복구가 필요하여 Redo Log에 기록이 되지만 임시 테이블의 Log는 Rollback이나 MVCC를 위한 일시적인 용도로만 존재하기 때문에 Redo Log에는 저장하지 않는다고 한다.

  • 일반 테이블 insert: insert 쿼리 발생 시 해당 레코드를 삽입 취소(삭제) 하는 정보를 저장하여 Rollback시 삽입된 데이터를 삭제한다.
  • 일반 테이블 update/delete: update/delete 쿼리의 기존값을 기억하여 Rollback시 쿼리의 기존값을 토대로 이전 상태로 복원하거나 삭제를 취소한다.
  • 임시 테이블 insert: 임시 테이블에 발생한 insert 쿼리의 Undo Log는 서버 실행 중인만 유지되며 Redo Log에는 기록이 되지 않고 서버가 꺼지면 임시 테이블도 사라진다.
  • 임시 테이블 update/delete: 마찬가지로 변경전 값을 저장하며 redo Log는 기록하지 않고 Rollback이나 MVCC에만 사용한다

 

 

Log로 관리하는 이유?

만약 로그가 아니라 이런 변경 상태를 기록하기 위해서 디스크에 저장한다면 물리적인 디스크에 저장하는 것은 구조상 느릴 수 밖에 없어 엄청난 성능 저하가 발생할 것이다.

속도를 빠르게 하기 위에 인메모리 저장소에 저장한다면 갑자기 장애가 발생하여 변경내용을 영속화 하기 전에 DB가 꺼지게 되면 데이터를 유실 될 수 있을것이다

 

이러한 문제점을 해결하는 현실적이고 검증된 방법이 바로 Write-Ahead Logging(WAL) 기법이라고하는 데이터의 변경사항을 먼저 로그에 기록한 뒤 실제 데이터는 나중에 비동기적으로 디스크에 적용하는 방법이다

 

즉, 메모리(Buffer Pool)의 변경이 곧바로 디스크에 쓰이지 않아도 장애 발생 시 로그를 통해 데이터를 복구할 수 있도록 보장하는 기술이며 MySQL의 InnoDB 스토리지 엔진 역시 WAL 방법을 사용한다.

이것이 Redo Log, Undo Log로 데이터의 지속성을 지키고 트랜잭션의 원자성, 격리성을 지키는 방법이다.

 

트랜잭션에서 Redo Log, Undo Log 흐름 예시

accounts 테이블의 balance의 값이 100일 때 아래의 업데이트 쿼리가 발생했다고 했을 때 Redo Log와 Undo Log가 동작하는 상황을 예시로 설명해보고자 한다.

UPDATE accounts SET balance = 200 WHERE id = 1;

 

  1. 업데이트 쿼리가 발생했다고 가정하면 InnoDB 엔진이 이를 처리하게 된다.
  2. Inno DB는 디스크에서 accounts 테이블의 해당 페이지를 메모리 내 Buffer Pool로 로딩하며 메모리에서 balance를 200으로 수정하지만 실제 디스크에는 아직 변경되지 않는다
  3. 트랜잭션이 롤백 될 경우 되돌릴 수 있도록 Undo Log에 변경 전 상태인 balance = 100을 저장한다.(MVCC에서 다른 트랜잭션이 과거 데이터를 참조할 때도 사용)
  4. Redo Log Buffer에 balance가 200으로 변경된 내용을 기록하는데 트랜잭션이 커밋 되었을 때 장애가 발생했을 경우 이 변경사항을 재반영하기 위함이다.
  5. 트랜잭션 사용자가 commit을 날리거나 auto commit이 켜져 있다면 지금 commit이 실행된다
  6. Redo Log Buffer에 저장된 내용이 디스크에 fsync()를 통해 기록되어 영구적으로 반영됨을 보장한다.
  7. Redo Log가 디스크에 안전하게 기록되었으므로 트랜잭션이 커밋을 완료한다.

** fsync()

  • 버퍼에 저장된 데이터를 디스크에 강제로 즉시 기록하는 시스템 함수이다.
  • 운영체제 레벨의 시스템 콜 명령으로 데이터베이스를 포함한 대부분의 시스템에서 '디스크에 데이터를 안전하게 저장했는가'를 보장할 때 사용한다고 한다
  • 보통 파일에 데이터를 쓴다고 했을때 실제로는 운영제제의 페이지 캐시(메모리)에만 저장이 되는데 write() 호출 후 컴퓨터가 꺼지면 메모리의 데이터가 날라가기 때문에 이를 막기 위해 fsync()를 사용한다고 한다.

 

 

** 참고 자료

728x90

'스터디 > DB' 카테고리의 다른 글

MVCC(Multi-Version Concurrency Control)  (0) 2025.04.29
S lock, IS lock, X lock, IX lock에 대해서 설명하기  (1) 2025.04.19