목차
1. Undo Log
언두 로그는 InnoDB 스토리지 엔진의 핵심 구성요소 중 하나로, DML로 변경되기 이전의 데이터를 저장합니다.
언두 로그의 주요 목적은 트랜잭션의 일관성을 지원하고, 트랜잭션 중 수행된 변경을 롤백할 수 있는 기능을 제공하는 것입니다.
언두 로그는 단일 읽기-쓰기 트랜잭션에 연관된 언두 로그 레코드들의 모음입니다.
언두 로그 레코드에는 가장 최근 변경을 롤백할 수 있도록 하는 정보를 포함되는데, 다른 트랜잭션이 일관된 읽기 작업을 위해 다른 트랜잭션이 변경하기 전의 데이터를 조회해야 할 경우, 변경 전 데이터는 언두 로그 레코드로부터 가져옵니다.
언두 로그는 롤백 세그먼트 안에 포함된 언두 로그 세그먼트 내에 존재하며, 롤백 세그먼트는 언두 테이블스페이스와 글로벌 임시 테이블스페이스 내에 존재합니다.
글로벌 임시 테이블스페이스 내 언두 로그는 사용자 정의 임시 테이블의 데이터를 변경 할 때 사용됩니다.
리두로그에 기록되는 언두 테이블스페이스 내 언두로그와는 달리, 글로벌 임시 테이블스페이스 내 언두 로그들은 크래시 복구에 필요하지 않기 때문에 리두 로그에 기록되지 않습니다.
각 언두 테이블스페이스와 글로벌 임시 테이블스페이스는 각각 최대 128개의 롤백 세그먼트를 지원합니다.
innodb_rollback_segments 시스템 변수는 롤백 세그먼트의 수를 정의합니다.
롤백 세그먼트가 지원할 수 있는 트랜잭션의 수는 롤백 세그먼트 내 언두 슬롯의 수와 각 트랜잭션이 필요로 하는 언두 로그 수에 따라 달라집니다.
롤백 세그먼트 내 언두 슬롯의 수는 InnoDB 페이지 크기에 따라 다릅니다.
InnoDB 페이지 크기 | 롤백 세그먼트 내 언두슬롯의 개수 (InnoDB page Size/16) |
4096 (4KB) | 256 |
8192 (8KB) | 512 |
16384 (16KB) | 1024 |
32768 (32KB) | 2048 |
65536 (64KB) | 4096 |
1) 역할과 목적
InnoDB 스토리지 엔진에서 언두 로그의 역할과 목적은 다음과 같습니다.
- 트랜잭션 롤백
트랜잭션 중 오류가 발생하거나 사용자가 롤백 명령을 수행하면, 언두 로그를 기반으로 변경 사항을 원래 상태로 되돌립니다.
- 예시: UPDATE로 값을 바꿨다가 취소하면, 언두 로그에 저장된 이전 값으로 복구됩니다.
- 목적: 데이터의 무결성과 일관성을 보장하기 위함 - MVCC 지원 (다중 버전 동시성 제어)
언두 로그는 과거 시점의 데이터를 읽을 수 있도록 도와줍니다.
REPEATABLE READ 격리 수준에서는 트랜잭션 시작 시점의 스냅샷을 기준으로 데이터를 보여줘야 하기 때문에, 언두 로그를 통해 예전 버전의 데이터를 제공합니다.
- 목적: 여러 트랜잭션이 동시에 읽고 쓸 수 있도록 하면서도, 격리 수준을 유지하기 위함 - 지연된 변경 처리 (Delayed Changes)
언두 로그를 이용하면 변경으로 '논리적으로' 먼저 수행하고, 이후에 실제로 데이터 파일을 변경하는 방식으로 안정적인 처리가 가능합니다.
- 목적: 트랜잭션이 완전히 커밋되기 전까지 변경을 확정하지 않고 유연하게 제어하기 위함 - 장애 복구의 보조 수단
장애 발생 시에는 주로 Redo 로그를 통해 복구하지만, 언두 로그도 함께 사용되어 트랜잭션의 원자성과 일관성을 보장합니다.
- 목적: 시스템 크래시 등 서버의 비정상 종료 시 안전하게 복구하기 위함
2) 작동 방식
언두 로그는 트랜잭션 시작 - DML수행 - 트랜잭션 종료 순으로 다른 작업을 수행합니다.
- 트랜잭션 시작
데이터가 변경되기 전이므로 언두로그는 발생하지 않습니다. - DML 수행 시
InnoDB 스토리지 엔진이 언두 로그에 기록을 시작합니다.
- INSERT: 추가된 레코드를 롤백(삭제)할 수 있도록 언두 로그에 기록합니다.
- UPDATE: 변경 전 값을 언두 로그에 기록합니다.
- DELETE: 삭제된 레코드 전체를 언두 로그에 기록합니다. - 트랜잭션 커밋
아직 해당 데이터를 읽고있는 다른 트랜잭션이 있다면 언두 로그는 커밋 후 즉시 삭제되지 않고 지연 삭제 됩니다.
이후 사용되지 않는 언두 로그를 Purge(청소)스레드가 백그라운드에서 정리합니다.
※ 주의
장시간 활성화된 트랜잭션이 있다면 Purge가 진행되지 않아, 언두 로그가 계속 쌓여 디스크 부족 현상이 발생할 수 있습니다.
3) 언두 로그 할당
하나의 트랜잭션은 작업 유형에 따라 최대 네 개의 언두로그를 할당받을 수 있습니다.
- 사용자 정의 테이블에 대한 INSERT 작업
- 사용자 정의 테이블에 대한 UPDATE 및 DELETE 작업
- 사용자 정의 임시 테이블에 대한 INSERT 작업
- 사용자 정의 임시 테이블에 대한 UPDATE 및 DELETE 작업
언두 로그는 필요에 따라 할당됩니다.
예를 들어, 일반 테이블과 임시 테이블 모두에서 INSERT, UPDATE 및 DELETE 작업을 수행하는 트랜잭션은 총 네 개의 언두 로그가 모두 할당됩니다.
일반 테이블에서 INSERT 작업만 수행하는 트랜잭션은 언두 로그 하나만 할당됩니다.
일반 테이블에서 작업을 수행하는 트랜잭션은 할당된 언두 테이블스페이스의 롤백 세그먼트로부터 언두 로그를 할당받습니다.
임시 테이블에서 작업을 수행하는 트랜잭션은 할당된 글로벌 임시 테이블스페이스의 롤백 세그먼트로부터 언두 로그를 할당받습니다.
트랜잭션에 할당된 언두 로그는 트랜잭션이 지속되는 동안 계속 연결된 상태로 유지됩니다.
예를들어, 트랜잭션이 일반 테이블에서 INSERT 작업을 수행할 때, 해당 트랜잭션에는 INSERT 작업용 언두 로그 객체가 하나 할당됩니다.
이 언두 로그는 트랜잭션 내에서 수행되는 모든 일반 테이블에 대한 INSERT 작업에 공통으로 사용되며, 각 INSERT마다 새로운 언두 로그가 별도로 생성되지는 않습니다.
이는 시스템 자원을 효율적으로 사용하기 위한 구조로, 트랜잭션 당 작업 유형별로 하나의 언두 로그만 사용하도록 설계되어 있습니다.
트랜잭션이 어떤 작업을 수행하느냐에 따라 필요한 언두로그 수가 달라지고, 이에 따라 InnoDB가 감당할 수 있는 최대 동시 트랜잭션 수도 달라집니다.
4) 최대 동시 트랜잭션 수 계산하기
최대 동시 트랜잭션 수는 InnoDB 스토리지 엔진이 한 시점에 동시에 처리할 수 있는 읽기-쓰기 트랜잭션의 최대 개수를 의미합니다.
여러 사용자가 동시에 데이터베이스에 접근하여 데이터를 삽입, 수정, 삭제하는 작업을 수행할 때, 각 트랜잭션은 내부적으로 언두 로그와 언두 슬롯 같은 리소스를 사용하게 됩니다.
그런데 이 리소스는 제한되어 있기 때문에, 동시에 처리할 수 있는 트랜잭션의 수에는 자연스럽게 상한이 생깁니다.
만약 이 한도를 초과하면, 새로 시작하려는 트랜잭션은 언두 슬롯을 할당받지 못해 실패하거나, 나중에 다시 시도해야 하는 상황이 발생할 수 있습니다.
이처럼 언두 구조에 기반한 InnoDB의 내부 설계는 전체 시스템의 안정성을 유지하는 동시에, 동시 트랜잭션 처리 능력에도 직접적인 영향을 줍니다.
다음은 각 작업 유형 별 InnoDB 가 감당할 수 있는 최대 동시 트랜잭션 수를 계산하는 수식입니다.
- 일반 테이블에 INSERT 또는 UPDATE 또는 DELETE 중 한 가지 작업만 수행하는 트랜잭션
(innodb_page_size / 16) * innodb_rollback_segments * number of undo tablespaces
- 일반 테이블에 INSERT와 UPDATE 혹은 DELETE 작업을 모두 수행하는 트랜잭션
(innodb_page_size / 16 / 2) * innodb_rollback_segments * number of undo tablespaces
- 임시 테이블에서 INSERT 작업만 수행하는 트랜잭션
(innodb_page_size / 16) * innodb_rollback_segments
- 임시 테이블에서 INSERT와 UPDATE 또는 DELETE 작업을 모두 수행하는 트랜잭션
(innodb_page_size / 16 / 2) * innodb_rollback_segments
참고
InnoDB가 이론적으로 감당 가능한 동시 트랜잭션 수에 도달하기 전에도 롤백 세그먼트의 언두 슬롯 고갈로 인해 트랜잭션 생성이 실패할 수 있습니다. 이 경우 트랜잭션을 다시 시도하면 됩니다.
2. Undo Tablespace
언두 테이블 스페이스는 언두 로그가 실제로 저장되는 물리적인 저장공간 입니다.
언두 로그는 메모리에서 먼저 생성되는데, 이후 그것은 디스크의 언두 테이블 스페이스에 저장됩니다.
1) 기본 언두 테이블 스페이스
두개의 기본 언두 테이블 스페이스(undo_001, undo002)는 MySQL 서버를를 최초 부팅할 때 생성됩니다.
언두 테이블 스페이스의 자동 잘림(truncate) 기능을 사용하기 위해 최소 두개의 언두 테이블 스페이스가 필요합니다.
언두 테이블 스페이스의 물리적인 데이터 파일의 이름은 undo_001, undo_002입니다.
MySQL 내부(데이터 딕셔너리)에서 사용되는 논리적인 이름은 innodb_undo_001, innodb_undo_002 입니다.
정리하자면 undo_001와 innodb_undo_001은 동일한 것이나, 다른 레벨에서 사용되는 언두 테이블스페이스의 이름입니다.
이는 information_schema.FILES를 조회하여 확인할 수 있습니다.
-- innodb_undo_001, innodb_undo_002과 undo_001, undo_002의 관계 확인하기
SELECT FILE_NAME, FILE_TYPE, TABLESPACE_NAME
FROM information_schema.FILES
WHERE TABLESPACE_NAME IN ('innodb_undo_001','innodb_undo_002')
+--------------+-------------+-------------------+
| FILE_NAME | FILE_TYPE | TABLESPACE_NAME |
+--------------+-------------+-------------------+
| ./undo_001 | UNDO LOG | innodb_undo_001 |
| ./undo_002 | UNDO LOG | innodb_undo_002 |
+--------------+-------------+-------------------+
언두 테이블스페이스는 MySQL 5.6.3 부터 도입된 innodb_undo_directory 변수의 설정된 경로에 생성됩니다.
만일 innodb_undo_directory 변수값을 설정하지 않았다면 datadir경로에 생성됩니다.
추가적인 언두 테이블스페이스는 SQL문을 사용하여 서비스 운영중에 추가로 생성할 수 있습니다.
2) 언두 테이블스페이스 사이즈
초기 언두 테이블스페이스 크기는 일반적으로 16MiB입니다.
단, truncate 작업으로 새로운 언두 테이블스페이스가 생성될 경우에는 초기 크기가 달라질 수 있습니다.
파일 확장 크기(file extension size)가 16MB보다 크고, 이전 확장이 마지막 1초 이내에 발생한 경우, 새 언두 테이블스페이스는 innodb_max_undo_log_size 변수에 설정된 값의 4분의 1 크기로 생성됩니다.
언두 테이블스페이스는 최소 16MB 단위로 확장됩니다.
이전 파일 확장이 0.1초 이내에 발생한 경우 이는 급격한 증가를 의미하는 것이기에 트래픽을 감당하기 위해 파일 확장 크기는 두 배로 증가합니다.
파일 확장 크기가 두 배 증가하는 것은 최대 256MB 가 될 때 까지 여러 번 발생할 수 있습니다.
이전 파일 확장이 0.1초보다 더 오래전에 발생한 경우, 확장 크기는 절반으로 감소하며, 이 역시 최소 16MB까지 여러 번 발생할 수 있습니다.
MySQL 8.0.23 부터는 AUTOEXTEND_SIZE 옵션을 사용할 수 있습니다.
언두 테이블스페이스에 AUTOEXTEND_SIZE 옵션이 정의되어 있는 경우, 테이블스페이스는 AUTOEXTEND_SIZE 설정값과 위의 로직에 의해 결정된 확장 크기 중 더 큰 값만큼 확장됩니다.
-- 테이블의 테이블스페이스 확장 크기를 설정 (AUTOEXTEND_SIZE)
CREATE TABLE t1 (c1 INT) AUTOEXTEND_SIZE = 4M;
ALTER TABLE t1 AUTOEXTEND_SIZE = 8M;
-- 테이블스페이스의 확장 크기를 설정 (AUTOEXTEND_SIZE)
CREATE TABLESPACE ts1 AUTOEXTEND_SIZE = 4M;
ALTER TABLESPACE ts1 AUTOEXTEND_SIZE = 8M;
3. Undo Tablespace 관리
1) 언두 테이블스페이스 추가하기
언두 로그의 크기는 장시간 실행되는 트랜잭션 도중 커질 수 있기 때문에, 추가적인 언두 테이블스페이스를 생성하면 개별 언두 테이블스페이스가 너무 커지는 것을 방지하는 데 도움이 될 수 있습니다.
언두 테이블스페이스는 CREATE UNDO TABLESPACE 구문을 사용하여 런타임 중에 생성할 수 있습니다.
-- 파일명만 지정
CREATE UNDO TABLESPACE tablespace_name ADD DATAFILE 'file_name.ibu';
-- 전체 경로로 파일명을 지정
CREATE UNDO TABLESPACE tablespace_name ADD DATAFILE '/newdir/file_name.ibu';
-- InnoDB에 알려진 경로 확인
SHOW GLOBAL VARIABLES LIKE 'innodb_directories';
+----------------------+----------------+
| Variable_name | Value |
+----------------------+----------------+
| innodb_directories | /newdir/ |
+----------------------+----------------+
언두 테이블스페이스 파일 이름은 반드시 .ibu 확장자를 가져야 합니다.
또한 전체 경로를 지정하여 파일을 생성할 수 있으나, 해당 경로는 InnoDB에 알려진 경로여야 합니다.
알려진 경로란 innodb_directories 변수에 정의된 경로를 의미합니다.
innodb_data_home_dir, innodb_undo_directory, datadir 변수에 정의된 디렉터리들은 innodb_directories 변수가 명시적으로 정의되었는지 여부와 관계없이 자동으로 innodb_directories 에 추가됩니다.
innodb_directories 시스템 변수는 Dynamic을 지원하지 않으므로 서비스 중에 알려지지 않은 경로에 테이블스페이스 파일을 생성하려면 my.cnf 파일 수정과 서버 재실행이 필요합니다.
언두 테이블스페이스의 이름과 경로를 확인하려면, information_schema.FILES을 조회하면 됩니다.
-- 생성된 언두 테이블스페이스 확인하기
SELECT TABLESPACE_NAME, FILE_NAME
FROM information_schema.FILES
WHERE FILE_TYPE LIKE 'UNDO LOG';
MySQL 인스턴스는 최대 127개의 언두 테이블스페이스를 지원하며, 여기에는 MySQL 인스턴스가 초기화될 때 생성되는 두 개의 기본 언두 테이블스페이스도 포함됩니다.
※ 주의
한 머신(서버)안에서 여러 MySQL 서버를 띄운 복제 환경일 경우, 소스와 각 복제본은 고유한 언두 테이블스페이스 파일 디렉토리를 가져야 합니다.
공통 디렉토리에
언두 테이블스페이스 파일 생성하게 되면 여러 서버가 공유하는 경로이므로 파일 이름 충돌이 발생할 수 있습니다.
2) 언두 테이블스페이스 삭제하기
CREATE UNDO TABLESPACE 문법을 사용하여 생성한 언두 테이블스페이스는,
런타임 중에 DROP UNDO TABLESPACE 문법을 사용하여 삭제할 수 있습니다.
언두 테이블스페이스를 삭제하려면 해당 테이블스페이스가 비어 있어야 합니다.
테이블스페이스를 비우려면 먼저 ALTER UNDO TABLESPACE 문법을 사용하여 해당 테이블스페이스를 비활성 상태(inactive) 로 전환해야 합니다.
비활성화 후 해당 테이블스페이스는 새로운 트랜잭션에 롤백 세그먼트를 할당하지 않게 됩니다.
ALTER UNDO TABLESPACE tablespace_name SET INACTIVE;
참고로 언두 테이블스페이스가 비활성화되었더라도 이미 존재하던 롤백 세그먼트를 사용 중인 트랜잭션은 완료될 수 있습니다.
뿐만 아니라 해당 트랜잭션 이전에 시작된 다른 트랜잭션들도 정상적으로 마무리될 수 있습니다.
트랜잭션이 완료되면 purge 시스템은 언두 테이블스페이스 내의 롤백 세그먼트를 해제하고, 언두 테이블스페이스는 초기 크기로 잘립니다(truncated).
언두 테이블스페이스가 비워지면 다음과 같이 삭제하는것이 가능해집니다.
DROP UNDO TABLESPACE tablespace_name;
추가로 필요한 경우, 언두 테이블스페이스를 비워진 상태로 유지했다가 ALTER UNDO TABLESPACE tablespace_name SET ACTIVE 구문을 통해 다시 활성화 할 수도 있습니다.
언두 테이블스페이스의 상태는 information_schema.INNODB_TABLESPACES 테이블을 조회하여 확인할 수 있습니다.
SELECT NAME, STATE
FROM information_schema.INNODB_TABLESPACES
WHERE NAME LIKE 'tablespace_name';
inactive 상태는 해당 언두 테이블스페이스 내의 롤백 세그먼트가 더 이상 새로운 트랜잭션에 사용되지 않음을 나타냅니다.
empty 상태는 언두 테이블스페이스가 비어 있어 삭제 가능하거나, ALTER UNDO TABLESPACE ... SET ACTIVE를 통해 다시 활성화할 수 있음을 나타냅니다.
비어 있지 않은 언두 테이블스페이스를 삭제하려고 시도하면 오류가 발생합니다.
기본 언두 테이블스페이스(innodb_undo_001 및 innodb_undo_002)는 삭제할 수 없습니다.
그러나 ALTER UNDO TABLESPACE tablespace_name SET INACTIVE 문을 사용하여 비활성화하는 것은 가능합니다.
기본 언두 테이블스페이스를 비활성화하기 전에, 그 자리를 대신할 테이블스페이스가 있어야 합니다.
참고로 언두 테이블스페이스의 자동 잘림(auto truncation)기능을 사용하려면 항상 최소 두 개의 활성 언두 테이블스페이스가 필요하다는 것을 인지하고 있어야 합니다.
3) 언두 테이블스페이드 이동하기
CREATE UNDO TABLESPACE 문으로 생성된 언두 테이블스페이스는 서버가 오프라인 상태일 때, 알려진 디렉터리로 이동할 수 있습니다.
알려진 디렉터리는 innodb_directories 변수에 의해 정의된 디렉터리들입니다.
innodb_data_home_dir, innodb_undo_directory, 그리고 datadir로 정의된 디렉터리는 innodb_directories 변수가 명시적으로 정의되었는지 여부와 관계없이 자동으로 innodb_directories 값에 추가됩니다.
이러한 디렉터리들과 그 하위 디렉터리는 시작 시 언두 테이블스페이스 파일을 찾기 위해 스캔됩니다.
언두 테이블스페이스 파일이 이들 디렉터리 중 하나로 이동되면, 시작 시 해당 언두 테이블스페이스로 인식됩니다.
기본 언두 테이블스페이스 (innodb_undo_001 및 innodb_undo_002)는 반드시 innodb_undo_directory 변수로 정의된 디렉터리에 위치해야 합니다.
innodb_undo_directory 변수가 정의되지 않은 경우, 기본 언두 테이블스페이스는 데이터 디렉터리(data directory)에 위치합니다.
기본 언두 테이블스페이스가 서버가 꺼진 상태에서 이동되었다면, 서버를 다시 시작할 때 innodb_undo_directory 변수를 새 디렉터리로 설정해야 합니다.
언두 로그의 I/O 패턴으로 인해, 언두 테이블스페이스는 SSD 저장소에 저장하는것이 가장 적합합니다.
4) 롤백 세그먼트 개수 설정하기
innodb_rollback_segments 변수는 각 언두 테이블스페이스와 전역 임시 테이블스페이스에 할당되는 롤백 세그먼트의 수를 정의합니다.
이 변수는 서버 시작 시 또는 서버가 실행 중일 때 구성할 수 있습니다
innodb_rollback_segments의 기본 설정 값은 128이며, 최대값도 128입니다.
4. Undo Tablespace 잘라내기 (Truncate)
언두 테이블스페이스 크기를 관리하기 위해 사용되는 잘라내기(truncation)기능에는 두 가지 방법이 있습니다.
이 두 기능은 각각, 혹은 혼용하여 사용가능합니다.
하나는 설정 변수로 활성화되는 자동화된 방법이고, 다른 하나는 SQL 문을 사용하여 수행하는 수동 방법입니다.
자동화된 방법은 언두 테이블스페이스 크기를 모니터링할 필요가 없으며, 일단 활성화되면 비활성화(deactivation), 잘라내기(truncation), 재활성화(reactivation) 과정을 수동 개입 없이 자동으로 수행합니다.
반면, 수동 잘라내기 방법은 언두 테이블스페이스를 언제 오프라인으로 전환해 잘라낼지 직접 제어하고자 할 때 채택될 수 있는 방법입니다.
예를 들어, 업무량이 많은 시간대에는 언두 테이블스페이스를 잘라내지 않도록 제어 할 수 있습니다.
1) 자동 잘라내기 (Automated Truncation)
언두 테이블스페이스의 자동 잘라내기를 위해서는 최소 두 개의 활성 언두 테이블스페이스가 필요합니다.
이렇게 하면 하나의 언두 테이블스페이스가 잘라내기를 위해 오프라인 상태가 되어도 다른 하나는 활성 상태로 유지됩니다.
기본적으로 MySQL 인스턴스는 최초 실행 시 두 개의 언두 테이블스페이스가 생성됩니다.
언두 테이블스페이스를 자동 잘라내기로 관리하려면, innodb_undo_log_truncate 변수가 활성화되어 있어야 합니다.
해당 변수는 기본값이 ON이므로 따로 정의하지 않았다면 활성화되어 있습니다.
SET GLOBAL innodb_undo_log_truncate=ON;
innodb_undo_log_truncate 변수가 활성화되면, innodb_max_undo_log_size 변수에 정의된 크기를 초과한 언두 테이블스페이스는 잘라내기의 대상이 됩니다.
innodb_max_undo_log_size 변수는 동적으로 설정 가능하며, 기본값은 1,073,741,824 바이트 (1024 MiB)입니다.
- 기본 혹은 사용자 정의 언두 테이블스페이스 중 innodb_max_undo_log_size 설정값을 초과하는 것들은 잘라내기를 위해 표시됩니다.
잘라낼 언두 테이블스페이스는 원형 방식(circular fashion) 으로 선택되어, 매번 동일한 테이블스페이스가 잘리는 일이 없도록 합니다. - 선택된 언두 테이블스페이스 내에 있는 롤백 세그먼트는 비활성화되어, 새로운 트랜잭션에 할당되지 않도록 합니다.
현재 해당 롤백 세그먼트를 사용 중인 기존 트랜잭션은 종료될 수 있도록 허용됩니다. - 해당 undo 테이블스페이스의 모든 롤백 세그먼트가 해제되면, truncate 작업이 수행되며 언두 테이블스페이스는 초기 크기로 잘라내어집니다.
- truncate 작업 직후 언두 테이블스페이스가 바로 사용된 경우에는 truncate 되었음에도 초기 크기보다 클 수 있습니다.
- 롤백 세그먼트는 재활성화되어 새로운 트랜잭션에 다시 할당될 수 있습니다.
2) 수동 잘라내기 (Manual Truncation)
수동으로 언두 테이블스페이스를 truncate(잘라내기)하려면 최소 3개의 활성 언두 테이블스페이스가 필요합니다.
자동 truncate가 활성화되어 있을 때를 대비하여 항상 2개의 활성 언두 테이블스페이스가 필요합니다.
3개의 언두 테이블스페이스가 있으면, 이 조건을 충족하면서 하나의 언두 테이블스페이스를 수동으로 오프라인으로 전환할 수 있습니다.
언두 테이블스페이스를 수동으로 truncate 하려면, 먼저 다음 구문을 통해 truncate할 언두 테이블스페이스를 비활성화해야합니다.
ALTER UNDO TABLESPACE tablespace_name SET INACTIVE;
언두 테이블스페이스가 비활성 상태로 표시되면, 해당 언두 테이블스페이스에서 롤백 세그먼트를 사용 중인 트랜잭션이 완료될 때까지 기다립니다.
또한 이전에 시작된 트랜잭션들도 모두 완료되어야 합니다.
트랜잭션들이 완료되면 purge 시스템이 해당 언두 테이블스페이스의 롤백 세그먼트를 해제하고,
언두 테이블스페이스는 초기 크기로 truncate 되어, 언두 테이블스페이스의 상태는 inactive(비활성) 에서 empty(비어 있음) 상태로 변경됩니다.
참고
ALTER UNDO TABLESPACE tablespace_name SET INACTIVE 구문으로 언두 테이블스페이스를 비활성화하면, purge 스레드는 다음 기회에 해당 언두 테이블스페이스를 찾아 truncate 대상으로 표시합니다.
한 번 truncate 대상으로 지정되면, purge 스레드는 더 짧은 간격으로 자주 실행되어 롤백 세그먼트를 빠르게 비우고 truncate 작업을 완료합니다.
언두 테이블스페이스의 상태는 information_schema.INNODB_TABLESPACES을 조회하여 확인할 수 있습니다.
SELECT NAME, STATE
FROM information_schema.INNODB_TABLESPACES
WHERE NAME LIKE 'tablespace_name';
언두 테이블스페이스가 empty 상태가 되면, 다음 구문으로 다시 활성화할 수 있습니다.
ALTER UNDO TABLESPACE tablespace_name SET ACTIVE;
3) 언두 테이블스페이스 자동 truncate 가속화
Purge 스레드는 언두 테이블스페이스를 비우고 truncate하는 역할을 담당합니다.
기본적으로 purge 스레드는 purge가 호출될 때마다 128번 중 한 번의 빈도로 언두 테이블스페이스를 truncate할 수 있는지 확인합니다.
이를 도식으로 표현하면 다음과 같습니다.
┌─────────────┐
│ Purge #1 │ → 일반 정리 작업
└─────────────┘
↓
┌─────────────┐
│ Purge #2 │ → 일반 정리 작업
└─────────────┘
↓
...
↓
┌──────────────┐
│ Purge #128 │ → 일반 정리 작업 + Truncate 대상 Undo TS 검사
└──────────────┘
↓
┌─────────────┐
│ Purge #129 │ → 일반 정리 작업
└─────────────┘
↓
...
↓
┌──────────────┐
│ Purge #256 │ → 일반 정리 작업 + Truncate 대상 Undo TS 검사
└──────────────┘
언두 테이블스페이스 truncate 대상 여부를 확인하는 빈도는 innodb_purge_rseg_truncate_frequency 변수로 제어됩니다.
이 변수의 기본값은 128입니다.
purge스레드가 언두 테이블스페이스를 검사하는 빈도를 높이고 싶다면, innodb_purge_rseg_truncate_frequency 값을 더 작은 수치로 낮추면 됩니다.
예를 들어, purge가 호출될 때마다 32번 중 한 번씩 언두 테이블스페이스를 검사하도록 하려면, 아래와 같이 설정하면 됩니다.
-- 현재 설정된 purge시 언두 테이블 스페이스 체크 주기 확인
SELECT @@innodb_purge_rseg_truncate_frequency;
+----------------------------------------+
| @@innodb_purge_rseg_truncate_frequency |
+----------------------------------------+
| 128 |
+----------------------------------------+
-- purge시 언두 테이블 스페이스 체크 주기를 32번으로 단축
SET GLOBAL innodb_purge_rseg_truncate_frequency=32;
5. Undo Log 저장 방식
언두 로그는 InnoDB의 테이블 스페이스 안에 저장됩니다.
버전에 따라 위치 및 저장되는 파일이 다릅니다.
MySQL 버전 | Undo 로그 저장 방식 |
5.6.3 미만 | 시스템 테이블 스페이스 ibdata1 파일 내부 |
5.6.3 이상 | 별도의 언두 테이블 스페이스 사용 가능 (선택사항) |
8.0 이상 | 기본적으로 별도 언두 테이블 스페이스에 생성 |
버전 별로 저장방식이 다르기에, 이를 유의하여 관리해야 합니다.
기본적으로 InnoDB는 언두 로그를 언두 테이블스페이스내의 롤백 세그먼트에 저장합니다.
각 롤백 세그먼트는 여러 개의 언두 슬롯을 가지고 있으며, 이 슬롯은 각각 하나의 트랜잭션이 사용하는 공간입니다.
트랜잭션이 시작되면 InnoDB는 사용 가능한 언두 슬롯을 하나 할당받고, 이 슬롯에 트랜잭션 중 발생하는 모든 변경 전 데이터를 기록합니다.
변경된 내용이 커밋되기 전까지 이 언두 로그는 계속 유지되며, 만약 트랜잭션이 롤백되면 해당 언두 로그를 이용해 이전 상태로 데이터를 되돌릴 수 있습니다.
언두 로그는 언두 로그 페이지 단위로 저장됩니다.
InnoDB는 필요에 따라 언두 로그 페이지를 할당하고, 언두 로그를 체인 형태로 연결하여 관리합니다.
이 체인은 purge 스레드에 의해 주기적으로 정리되며, 커밋된 트랜잭션의 언두 로그는 더 이상 필요하지 않게 되면 삭제됩니다.
또한, 언두 로그는 임시 테이블용 언두 로그와 일반 데이터용 언두 로그로 분류되며, 각각 별도의 테이블스페이스와 롤백 세그먼트를 사용합니다.
이러한 구조는 성능 최적화와 관리 효율성을 높이기 위한 것입니다.
:: 참고
MySQL :: MySQL 8.0 Reference Manual :: 17.6.6 Undo Logs
MySQL :: MySQL 8.0 Reference Manual :: 17.6.3.4 Undo Tablespaces
'Database > MySQL' 카테고리의 다른 글
[MySQL] Error 1300: Invalid utf8mb4 character string: '' 에러 해결법 (0) | 2025.05.23 |
---|---|
[MySQL] Change Buffer 체인지 버퍼 (0) | 2025.04.10 |
[MySQL] InnoDB Cluster 3부작 : 3. MySQL InnoDB Cluster Metadata 생성 및 MySQL Router 구성하기 (0) | 2025.04.01 |
[MySQL] InnoDB Adaptive 시스템 변수 (0) | 2025.03.27 |
[MySQL] InnoDB Cluster 3부작 : 2. Group Replication (2) - 구성하기 (0) | 2025.03.19 |