[MySQL] 리두 로그(Redo Log)

신찬규·2024년 7월 2일

MySQL

목록 보기
11/13

1. 리두 로그(Redo Log)란?

리두 로그(Redo Log)는 예상치 못한 문제로 인해 MySQL이 비정상적으로 종료됐을 때 데이터 파일에 기록되지 못한 데이터를 잃지 않게 해주는데 사용되며, 디스크에 저장되는 로그이다. 리두 로그에는 SQL이나 로우 레벨 API 호출로 인한 InnoDB 테이블 데이터의 변경 요청들이 기록된다. 그래서 MySQL에 장애가 발생하더라도, 리두 로그에 저장된 기록들을 바탕으로 복구가 가능한 것이다! MySQL은 데이터 변경 내용을 디스크에 기록하기 전에 리두 로그로 먼저 기록하는데, 그래서 리두 로그를 Write Ahead Log의 줄임말로 WAL라고도 부른다. 리두 로그에 기록되는 단위를 리두라고 하며, 각 리두에는 계속 증가하는 번호가 붙는데 이 번호를 LSN(Log Sequence Number)이라고 한다. 이 LSN은 아래에서 설명할 체크포인트와 관련이 있다.

2. 리두 로그와 버퍼 풀

InnoDB 버퍼 풀은 데이터 캐시 기능과 쓰기 버퍼링 기능을 제공하는데, 리두 로그는 버퍼 풀의 쓰기 버퍼링 기능과 밀접한 관계가 있다. 버퍼 풀의 쓰기 버퍼링 기능을 향상시키기 위해선 먼저 둘의 관계를 이해해야 한다.

버퍼 풀 내에 상주하고 있는 페이지는 변경이 발생하지 않은 경우 클린 페이지(Clean Page), 변경이 가해진 경우 더티 페이지(Dirty Page)라고 한다. 더티 페이지는 변경이 가해졌기 때문에 해당 변경을 기록하는 리두 로그를 가지게 된다. 또한, 더티 페이지는 버퍼 풀과 디스크의 데이터 상태가 다르기 때문에 동기화 작업이 반드시 필요하다. InnoDB 스토리지 엔진은 주기적으로 체크포인트라는 이벤트를 발생시켜 버퍼 풀의 더티 페이지와 관련된 리두 로그를 디스크로 동기화한다. 체크포인트가 발생하면 체크포인트 LSN보다 작은 LSN을 가진 리두들은 모두 디스크로 동기화해야 하며, 물론 각 리두와 관련된 더티 페이지들도 모두 디스크로 동기화해야 한다. 그렇기 때문에, 리두 로그의 전체 파일 크기가 버퍼 풀에 상주할 수 있는 더티 페이지의 크기를 결정하게 된다.

아래 예시를 통해 리두 로그의 전체 파일 크기와 버퍼 풀에 상주할 수 있는 더티 페이지의 크기의 관계에 대해 알아보자.

  1. InnoDB 버퍼 풀은 100GB이며, 리두 로그 파일의 전체 크기는 100MB인 경우
  2. InnoDB 버퍼 풀은 100MB이며, 리두 로그 파일의 전체 크기는 100GB인 경우

1번은 2번보다 버퍼 풀의 크기가 더 크지만, 리두 로그 파일의 전체 크기는 더 작다. 2번은 1번보다 버퍼 풀의 크기가 더 작지만, 리두 로그 파일의 전체 크기는 더 크다. 버퍼 풀의 더티 페이지 비율은 어느 경우가 더 클까? 데이터 페이지의 크기가 16KB, 평균 리두 로그의 크기가 4KB라고 하자.

1번의 경우 버퍼 풀에 100MB / 4KB = 25,000개의 더티 페이지가 존재할 수 있다. 가능한 전체 더티 페이지의 크기는 16KB ×\times 25,000 = 400MB이다. 버퍼 풀의 전체 크기는 100GB이지만, 더티 페이지는 400MB 밖에 상주할 수 없기 때문에 쓰기 버퍼링의 효과는 미미할 것이다.

2번의 경우 버퍼 풀에 100GB / 4KB = 25,000,000개의 더티 페이지가 존재할 수 있다. 가능한 전체 더티 페이지의 크기는 16KB ×\times 25,000,000 = 400GB이다. 물론 버퍼 풀의 전체 크기가 100MB이기 때문에 그럴 순 없겠지만 말이다.

두 경우 모두 좋은 방법은 아니지만, 1번의 경우 버퍼 풀의 크기에 비해 쓰기 버퍼링 효과를 거의 못 보는 상황이다. 데이터베이스의 성능 향상을 위해 버퍼 풀의 크기를 무작정 올리기만 해서는 안되는 것을 알 수 있다.

3. 리두 로그와 로그 버퍼

위 설명에서 리두 로그는 디스크에 저장된다고 했다. 그러나, 데이터 변경 사항이 발생할 때마다 리두 로그를 생성해야 하는데 그때마다 디스크 I/O를 하게 된다면 큰 성능 저하가 생길 것이다. 이를 개선하기 위해 리두 로그는 쓰기 비용이 낮은 자료구조와 로그 버퍼를 이용한다. 로그 버퍼에 버퍼링된 리두 로그를 디스크로 플러시 하는 기준은 innodb_flush_log_at_trx_commit 시스템 변수를 통해 설정할 수 있다. 리두 로그는 트랜잭션이 커밋되면 즉시 디스크로 기록되도록 설정하는 것을 권장한다. 그렇지 않으면 MySQL이 비정상적으로 종료됐을 때 트랜잭션의 커밋 내용이 리두 로그로 남아있지 않을 수 있고, 결국 장애 복구에 문제가 생길 수 있다.

4. 궁금했던 점

필자는 리두 로그를 공부하면서 트랜잭션을 커밋할 때마다 리두 로그를 디스크로 기록한다면 성능에 문제가 있는게 아닐까 궁금했다. 이는 위에서 설명한대로 쓰기 비용이 낮은 자료구조와 로그 버퍼를 통해 해결한다고 한다. 리두 로그는 여러 개의 고정 크기 파일을 연결해서 순환 고리처럼 사용한다. 그렇기 때문에 순차 I/O가 가능해 랜덤 I/O보다 조금 더 빠르게 쓰기가 가능하다. 참고로, 더티 페이지의 경우에는 순차 I/O가 아닌 랜덤 I/O가 주로 발생하기 때문에 훨씬 더 많은 비용이 든다.

참고 자료

profile
느려도 조금씩 꾸준하게

0개의 댓글