티스토리 뷰

데이터베이스

MySQL 언두 로그

3Juhwan 2024. 7. 4. 13:48
Real MySQL 8.0을 읽고 저의 뇌구조에 맞게 정리한 내용입니다. 

 

 

목차

  1. 언두 로그가 어떻게 사용되는지
  2. 언두 테이블스페이스 관리
  3. 언두 로그로 발생할 수 있는 문제
  4. 발생하는 문제를 MySQL 8.0 버전에서 해결
  5. 언두 로그 모니터링하기
  6. 읽으면서 생긴 질문

 

언두 로그가 어떻게 사용되는지

DML(INSERT, UPDATE, DELETE) 실행으로 데이터가 변경되기 전에 이전 버전 데이터를 백업한다. 백업된 데이터를 언두 로그라고 한다. 

 

트랜잭션 보장

  • 트랜잭션이 롤백되면 트랜잭션 도중 변경된 데이터를 변경 전 데이터로 복구해야 한다.
  • 이때 언두 로그에 백업해둔 이전 버전의 데이터를 이용해 복구한다. 

 

격리 수준 보장

  • 특정 커넥션에서 데이터를 변경하는 도중 다른 커넥션에서 데이터를 조회하는 경우에, 트랜잭션 격리 수준에 맞게 변경 중인 레코드를 읽지 않고 언두 로그에 백업한 데이터를 읽어서 반환하기도 한다. 

 

언두 테이블스페이스 구조

언두 테이블스페이스 구조

  • 하나의 언두 테이블스페이스는 1개 이상 128개 이하의 롤백 세그먼트를 가진다. 
  • 하나의 롤백 세그먼트는 1개 이상의 언두 슬롯을 가진다. 
  • 하나의 롤백 세그먼트는 InnoDB의 페이지 크기를 16바이트로 나눈 값의 개수만큼 언두 슬롯을 가진다. 
  • 하나의 트랜잭션은 필요에 따라 최대 4개의 언두 슬롯을 사용한다. 
  • 사용하는 언두 슬롯의 개수는 트랜잭션이 실행하는 INSERT, UPDATE, DELETE 문장의 특성에 따른다. 
  • 일반적으로 트랜잭션이 임시 테이블을 사용하지 않으므로 하나의 트랜잭션은 대략 2개 정도의 언두 슬롯을 필요로 한다. 

 

최대 동시 처리 가능 트랜잭션의 개수 

 

최대 동시 트랜잭션 수 = (InnoDB 페이지 크기) / 16 * (롤백 세그먼트 개수) * (언두 테이블스페이스 개수)

 

 

InnoDB 기본 설정

  • 페이지 크기 = 16KB
  • innodb_rollback_segments = 128
  • innodb_undo_tablespaces = 2
  • 약 131,072개 정도의 트랜잭션이 동시에 처리 가능하다. 

 

언두 테이블스페이스 관리

MySQL 5.6 이전 버전

  • 시스템 테이블스페이스에 저장된다. 
  • 시스템 테이블스페이스의 언두 로그는 MySQL 서버가 초기화될 때 생성되기 때문에 확장의 어려움이 있다. 

 

MySQL 5.6 버전

  • innodb_undo_tablespaces 시스템 변수를 도입했다. 
  • innodb_undo_tablespaces를 2보다 큰 값으로 설정하면 InnoDB 스토리지 엔진은 별도의 로그 파일을 사용한다. 
  • 여전히 시스템 테이블스페이스를 사용할 수 있다. 

 

MySQL 8.0 이후 버전 

  • innodb_undo_tablespaces 시스템 변수는 비활성화됐다. 
  • 항상 별도의 로그 파일에 기록한다. 

 

언두 로그로 발생할 수 있는 문제

1. 대용량 데이터를 처리하면 사용하는 공간이 급격하게 늘어남

  • MySQL 5.5 이전 버전의 MySQL에서는 한 번 증가된 언두 로그 공간은 줄어들지 않았다. 
  • 예를 들어, 테이블에 1억 건의 레코드(100GB)가 있는 상황에서 전체 데이터를 삭제한다.
  • 삭제할 데이터는 언두 로그에 복사되어야 하고 테이블 크기만큼 언두 로그의 공간 사용량(100GB)이 늘어난다. 

 

2. 트랜잭션이 오래 되는 지속되는 경우 사용하는 공간이 급격하게 늘어남

  • 트랜잭션이 종료되었다고 언두 로그를 바로 지울 수 있는 것은 아니다.
  • 예를 들어, 트랜잭션 A, B, C가 존재한다. A가 먼저 시작되고 이후에 B, C가 실행되고 종료된다. 
  • 트랜잭션 B, C는 UPDATE, INSERT 등의 쿼리를 사용하여 언두 로그가 쌓였다. 
  • A가 종료되지 않았기에 B, C에서 쌓인 언두 로그는 삭제되지 않는다. 

 

3. 언두 로그의 공간 사용량이 증가하면 단순 레코드 조회 쿼리를 처리하는 시간이 길어짐

  • 단순히 레코드를 조회하는 쿼리가 있다고 하자. 
  • 조회를 위해 언두 로그의 이력을 어느 정도 스캔해야 필요한 레코드를 찾을 수 있다. 
  • 언두 로그의 사용량이 많아질수록 스캔할 데이터가 많아진다. 

 

언두 로그로 발생하는 문제를 8.0 버전에서 해결

MySQL 5.5 버전까지는 언두 로그 사용량이 많아지면 공간을 줄일 방법이 없었고, 새로운 MySQL 서버를 열어야 했다. 이 문제를 MySQL 8.0에서 해결했다. 

 

MySQL 8.0이 해결한 방법

  • 언두 로그를 돌아가며 순차적으로 사용하여 디스크 공간을 줄일 수 있게 되었다. 
  • 서버가 필요한 시점에 자동으로 줄여준다. 

 

언두 로그 테이블스페이스 동적으로 변경

MySQL 8.0부터 언두 로그 테이블스페이스를 동적으로 변경할 수 있다. 언두 테이블스페이스 공간을 필요한 만큼만 남기고 불필요하거나 과도하게 할당된 공간을 운영체제로 반납하는 것을 'Undo tablespace truncate'라고 한다. 

 

자동 모드

  • 트랜잭션이 커밋되면 더이상 언두 로그에 복사된 값이 필요하지 않다. 
  • InnoDB 스토리지 엔진의 퍼지 스레드가 주기적으로 깨어나서 삭제한다. 이것을 언두 퍼지(Undo Purge)라고 한다. 
  • MySQL 서버의 innodb_undo_log_truncate 시스템 변수가 ON으로 설정하면 된다. 
  • 빈도는 innodb_purge_rseg_truncate_frequency 시스템 변수 값을 조절하면 된다. 

 

수동 모드

  • innodb_undo_log_truncate 시스템 변수가 OFF인 상태
  • 또는 자동 모드로 반납되는 언두 테이블스페이스 공간이 부진한 경우
  • 언두 테이블스페이스를 비활성화하고 퍼지 스레드가 깨어난다. 
  • 퍼지 스레드는 비활성화된 언두 테이블스페이스를 찾아 불필요한 공간을 삭제하고 비활성을 푼다. 
  • 수동 모드는 언두 테이블스페이스가 3개 이상 있어야 동작한다. 


언두 로그 모니터링하기

활성 상태의 트랜잭션이 장시간 유지되는 것은 성능상 좋지 않다. 항상 모니터링을 하자. 

 

-- // MySQL 서버의 모든 버전에서 사용 가능한 명령
mysql> SHOW ENGINE INNODB STATUS \G

-- // MySQL 8.0 버전에서 사용 가능한 명령
mysql> SELECT count
	FROM information_schema.innodb_metrics
	WHERE SUBSYSTEM='transaction' AND NAME='trx_rseg_history_len';

 

 

읽으면서 생긴 질문

 

[3. 언두 로그로 발생할 수 있는 문제]

 

트랜잭션 B, C와 트랜잭션 A가 무슨 상관이지? 트랜잭션 B, C가 종료되면 언두 로그를 지워도 되는 거 아닐까?

  • 언두 로그의 목적 중 하나인 격리 수준 관련 처리를 위해서일 것이다.
  • 동시에 실행되는 트랜잭션의 경우에 언두 로그가 지속되어야 격리 수준 보장이 가능할 것이다. 

 

링크
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday