AWS 기술 블로그

RDS MySQL 과 Aurora MySQL 에서 Innodb purge 작업 최적화 하기

이 글은 AWS Database Blog에 게시된Achieve a high-speed InnoDB purge on Amazon RDS for MySQL and Amazon Aurora MySQL by Lei Zeng을 한국어 번역 및 편집 하였습니다.

Purge 는 MySQL 데이터베이스의 정리 작업입니다. InnoDB 스토리지 엔진은 다중 버전 동시성 제어(MVCC)나 롤백 작업에 더 이상 필요하지 않은 언두 로그와 삭제로 표시된 테이블 레코드를 정리하기 위해 이를 사용합니다. 애플리케이션은 사전에 가장 높은 쓰기 처리량을 달성하는 것을 목표로 데이터베이스 설계를 지향하지만 백그라운드에서 purge 가 적시에 진행될 수 있는지 확인하는 경우에도 마찬가지로 중요합니다. 대량의 데이터 변경이 발생하는 상황에서 purge 작업 진행이 느려지는 불균형한 상황에서는 데이터베이스 성능이 저하될 수 있습니다.

이 글에서는 Amazon Relational Database Service(Amazon RDS) for MySQL DB 인스턴스와 Amazon Aurora MySQL-Compatible Edition DB 클러스터에서 purge 처리를 빠르게 하기 위한 일련의 설계와 튜닝 전략에 대해서 설명하겠습니다. 먼저 MySQL 데이터베이스 내부에 대한 이해를 돕기 위해서 purge가 작동하는 방식을 간략하게 소개하겠습니다. 그런 다음 purge작업에 어려움을 주는 일반적인 상황과 이때 적용할 수 있는 최적화 방법에 대해 설명하겠습니다. 이 글에서는 MySQL 8.0을 기반으로 하며 대부분의 권장 사항은 일반 MySQL 데이터베이스에 적용할 수 있습니다. 또한 Amazon 관리형 데이터베이스 서비스에 대한 구체적인 고려 사항도 설명하겠습니다.

purge 작동 방식의 이해

다른 많은 관계형 데이터베이스 시스템(RDBMS)과 마찬가지로 MySQL은 MVCC를 구현해서 데이터 액세스 시 동시에 읽기와 쓰기 작업이 가능합니다. MVCC의 핵심 아이디어는 트랜잭션이 테이블 레코드를 업데이트할 때 데이터베이스 엔진이 테이블에 새로운 버전의 데이터를 만드는 것입니다. 이전 데이터 버전은 물리적으로 제거하지 않고 삭제로만 표시됩니다. 쿼리는 적절한 데이터 버전을 선택하여 원하는 격리 수준에서 자체적인 데이터베이스 뷰를 만들 수 있습니다. 이렇게 하는 가장 큰 이점은 읽기와 쓰기가 서로를 차단하지 않는 다는 것 입니다. 쓰기가 새 버전에서 작업하는 동안 읽기는 항상 이전 데이터 버전에 액세스할 수 있습니다. 테이블 레코드의 여러 버전으로 보관할 수 있는 기능은 데이터베이스 엔진이 트랜잭션 내에서나 장애 복구(Crash Recovery) 중에 롤백 작업을 수행하는 데 유리합니다.

확장 가능한 기능인 MVCC에는 유일한 제약이 있습니다. 이는 삭제 표시된 테이블 레코드는 언젠가는 가비지 컬렉션(Garbage Collection) 되어져야 한다는 것입니다. 다양한 데이터베이스 엔진에는 자체적인 버전 추적이나 가비지 컬렉션(Garbage Collection) 메커니즘이 포함 되어 있습니다. 일반적인 문제는 대량의 트랜잭션으로 인해 가비지 컬렉션(Garbage Collection) 이 따라잡을 수 없을 만큼 빠르게 오래된 데이터 버전이 생성되어 테이블 구조에 오래된 데이터 버전의 거대한 백로그가 생기는 경우 발생할 수 있습니다. 표면적으로 이는 스토리지 사용량의 예상치 못한 증가를 초래합니다. 또한 그 상황에서 이전 버전을 확인하면서 읽기 작업을 수행하기 위한 추가 I/O 작업이 필요합니다. 이런 추가 I/O 소모는 시스템 리소스의 경합을 유발시켜 잠재적으로 전체 데이터베이스 성능을 저하시킵니다.

MySQL 데이터베이스에서 InnoDB는 MVCC 와 롤백 작업을 지원하기 위해 언두 로그를 핵심 데이터 구조로 사용합니다. 테이블 레코드가 변경되면 이전 데이터 버전이 언두 로그에 저장됩니다. 동일한 테이블 레코드에 관련된 모든 언두 로그는 서로 연결되어 버전 체인을 구성합니다. 양날의 검과 같은 존재인 purge는 가비지 콜렉션 프로세스로서 언두 로그 뿐만 아니라 해당 로그가 참조하는 삭제 표시된 테이블 레코드도 정리합니다. 본질적으로 purge는 InnoDB의 트랜잭션 시스템의 필수적인 요소로 간주됩니다.

다음 그림은 innodb purge 의 상위 레벨에서의 디자인과3단계 워크플로우를 보여주고 있습니다.

  1. 트랜잭션이 시작되면 롤백 세그먼트가 할당됩니다. 롤백 세그먼트는 언두 테이블스페이스에 복수개의 언두 로그 페이지로 구성됩니다. 테이블 레코드가 저장된 데이터 페이지와 마찬가지로 언두 로그 페이지는 읽거나 쓰기 위해서는 InnoDB 버퍼 풀에 로딩되어 져야 합니다.
  2. 트랜잭션이 테이블의 데이터를 변경하면 언두 로그 레코드를 만듭니다. 언두 로그 레코드에는 테이블 ID, 클러스터 인덱스, 변경 전의 이전 데이터 버전과 같이 테이블 레코드의 변경 사항을 롤백 하는 데 필요한 관련 정보가 포함됩니다. INSERT, DELETE, UPDATE 문에 대한 다양한 유형의 언두 로그 레코드가 있습니다. 나중에 제거해야 하는지 여부에 따라 별도의 언두 로그로 그룹화됩니다.
  3. 커밋하는 동안 트랜잭션은 트랜잭션 시리얼 번호(trx_no)를 가져와 언두 로그에 씁니다. 제거해야 할 언두 로그가 있는 경우 trx_no 로 정렬된 롤백 세그먼트 히스토리 리스트(rollback segment history list)에 추가됩니다. InnoDB 트랜잭션 시스템은 trx_no를 사용하여 모든 커밋된 트랜잭션의 순서를 추적합니다. 그런 의미에서 이 히스토리 리스트은 데이터베이스 전체의 글로벌 리스트와 같습니다.
  4. purge는 멀티스레드 작업입니다. purge 스레드의 수는 innodb_purge_threads파라미터를 설정해서 사용됩니다. 일반적으로 purge 의 코디네이터는 하나이고 worker 스레드는 복수개로 수행됩니다. 이러한 스레드는 다음의 3단계로 구성된 purge 작업을 지속적으로 반복 수행합니다.

a.purge 코디네이터 스레드는 삭제 할 준비가 된 언두 로그가 있는지 확인합니다. 있으면 언두 레코드를 파싱하고 테이블 ID별로 정렬해서 배치로 가져옵니다. 그런 다음 각 그룹을 처리를 위해 worker 스레드에 할당합니다.

  1. purge worker 스레드는 테이블 ID별로 언두 로그 레코드를 병렬로 처리합니다. 언두 로그 레코드의 정보를 사용하여 클러스터 인덱스, 보조(Secondary) 인덱스, BLOB 컬럼의 레코드를 포함하여 삭제 표시된 레코드를 식별하고 삭제합니다. 정리 후 데이터 페이지에 데이터가 너무 적으면 다른 페이지와 병합하여 스토리지를 최적화시킵니다.
  2. 여러 배치의 언두 로그가 처리된 후 purge 코디네이터 스레드가 롤백 세그먼트 히스토리 리스트에서 제거하여 롤백 세그먼트를 해제합니다. MySQL은 innodb_undo_log_truncate라는 옵션을 제공하여 언두를 자동으로 잘라냅니다. 이는 언두 테이블스페이스가 innodb_max_undo_log_size에서 지정한 크기 제한을 초과하고 내부에 포함된 모든 롤백 세그먼트가 해제될 때 물리적인 스토리지 공간을 줄이기 위한 것입니다. 이 단계가 완료되면 purge 코디네이터 스레드가 다른 purge 사이클을 다시 시작합니다.

자동 언두 테이블스페이스 잘라내기(Truncate) 옵션은 Aurora MySQL 호환 버전인 3.06.0 이상에서 사용할 수 있습니다.

 

읽기 쓰기 워크로드의 균형 맞추기

트랜잭션이 INSERT, DELETE, UPDATE와 같은 DML 문을 사용하여 레코드를 수정하는 경우 InnoDB는 다양한 유형의 언두 로그 레코드를 만듭니다. 그러나 모든 유형의 언두 로그 레코드를 제거할 필요는 없습니다. INSERT 명령문의 언두 로그에는 이전 데이터 버전이 포함되어 있지 않으므로 트랜잭션이 커밋된 직후에 제거되고 롤백 세그먼트 히스토리 리스트에 추가되지 않습니다.

DELETE, UPDATE 명령문에서 생성된 언두 로그 레코드는 테이블 레코드가 삭제되거나 업데이트되기 전에 이전 데이터 버전을 저장하므로 제거 작업의 대상이 됩니다. 다른 동시 SELECT 쿼리나 오픈 트랜잭션은 MVCC의 목적을 위해 일관된 읽기를 구성하기 위해 이에 액세스해야 합니다. InnoDB는 활성화된 쿼리나 트랜잭션을 위한 언두 로그의 가시성을 추적하는 메커니즘으로 읽기 뷰(read view)를 사용합니다. 또한 언두 로그를 제거하는 것이 안전한지를 결정하기 위해 언두 코디네이터 스레드에 의해 사용됩니다.

언두 로그를 생성하고 사용하는 데이터베이스 워크로드는 Purge 스레드의 작동 방식에 직접적인 영향을 미칩니다. 언두 로그는 trx_no의 오름차순(Asc)으로 롤백 세그먼트 히스토리 리스트에서 Purge 됩니다. 언두 로그를 제거할 수 없는 경우 다른 테이블에 속하더라도 trx_no가 더 높은 다른 로그가 Purge 되는 것을 차단합니다. 즉 Purge작업은 데이터베이스 전체의 글로벌 작업이며 장기 실행 쿼리나 트랜잭션은 이후 수행된 트랜잭션의 언두 레코드 Purge 작업을 차단합니다. Purge 로 항상 문제가 많이 발생하는 MySQL 데이터베이스에서는 데이터베이스 워크로드의 시점, 동시성, 트랜잭션 특성을 검토하는 것이 좋습니다.

한 가지 전략은DELETE 문 대신 DROP PARTITION 이나 DROP TABLE 문을 실행함으로써 언두 로그를 생성하지 않을 수 있습니다. 다음 다이어그램에서 알 수 있듯이 DROP PARTITION을 통해 데이터의 하위 집합을 삭제할 수 있도록 테이블을 파티션화 하면 Purge 를 피할 수 있습니다. 또한 테이블의 많은 양의 데이터를 Delete 하려는 경우 새 테이블을 만들고 여기에 데이터를 복사한 다음 이전 테이블을 삭제하고 원본 테이블명으로 변경하는 것이 하나의 방법이 될 수 있습니다.

또 다른 전략은 DELETE 나 UPDATE 문의 실행이 많은 시간에 장시간 실행되는 SELECT 쿼리를 피하는 것입니다. 읽기 뷰(Read View)가 언두 로그를 유지하면서 purge를 차단할 수 있기 때문입니다. max_execution_time을 사용하면 최대 수행 시간 제한을 설정하여 너무 오래 실행되는 SELECT 쿼리를 자동으로 중지할 수 있습니다. 또다른 것은 트랜잭션 격리 수준을 REPEATABLE READ에서 READ COMMITTED로 바꾸는 것입니다. 이렇게 하면 SQL 문에서 생성된 읽기 뷰(Read View)의 범위가 줄어들어 언두 로그가 purge 되어 차단될 가능성이 낮아집니다.

Aurora MySQL은 모두 동일한 공유 클러스터 스토리지 볼륨을 사용하는 하나 이상의 DB 인스턴스로 구성된 클러스터형 데이터베이스입니다. InnoDB purge 구현은 클러스터링 토폴로지의 영향을 받습니다. Aurora MySQL DB 클러스터를 사용하는 경우 Amazon RDS for MySQL DB 인스턴스와 비교할 때 다음과 같은 차이점이 있습니다.

    • purge가 데이터베이스 전체의 글로벌 작업이라는 개념은 Aurora MySQL의 데이터베이스 아키텍처에서도 동일하게 적용됩니다. purge는 기본(Writer) DB 인스턴스에서 실행됩니다. 그러나 읽기 뷰를 생성하기 때문에 Aurora 복제본(Reader) DB 인스턴스의 SELECT 쿼리에 의해 차단될 수 있습니다. 또한 Aurora 글로벌 데이터베이스에서 Secondary DB 클러스터의 SELECT 쿼리는 Primary DB 클러스터의 purge를 차단할 가능성도 있습니다.
    • Aurora 복제(Reader) DB 인스턴스에서의 READ COMMITTED 격리 수준은 purge 스레드에서 장시간 수행되는 SELECT 쿼리의 영향을 줄이도록 최적화되었으며 Aurora MySQL의 특정 기능은 변함없이 수행될 수 있습니다. 쿼리 결과는 MySQL의 디폴트인 READ COMMITTED 격리화 수준을 사용하는 Primary DB 인스턴스의 결과와 약간 다를 수 있지만 여전히 ANSI SQL 표준을 준수합니다. DB 클러스터 파라미터 그룹이나 세션 수준에서 aurora_read_replica_read_committed파라미터를 ON으로 설정하여 이 기능을 활성화할 수 있습니다.

 

 

테이블과 인덱스 구조 최적화

언두 로그 외에도 InnoDB 테이블에서 삭제 표시된 테이블 레코드도 purge 작업의 대상입니다. 일반적으로 테이블 레코드는 클러스터형 인덱스, 보조(Secondary) 인덱스, Innodb row format에 따라 외부에 저장된 가변 길이 컬럼과 같이 테이블 행 데이터를 저장하거나 가리키는 다양한 데이터 구조를 나타냅니다. 언두 로그 레코드에는 테이블 ID와 클러스터형 인덱스만 포함되므로 purge 스레드는 관련된 다른 삭제 표시된 테이블 레코드를 식별해야 하며 만약 존재하는 경우 이를 삭제해야 합니다. 이는 purge 작업에서 가장 중요한 부분이 될 수 있습니다.

보조 인덱스가 purge 작업에 어떤 영향을 미치는지에 대한 예를 살펴보겠습니다. 다음 그래프는 두개의 Aurora MySQL DB 클러스터의 Amazon CloudWatch 메트릭  RollbackSegmentHistoryListLength를 비교해서 보여주고 있습니다. 두 클러스터 모두 r7g.2xlarge 의 기본(Writer) DB 인스턴스를 가지고 있으며 Sysbench oltp_write_only.lua 유형 워크로드를 사용하여 80GB 사이즈의 테이블 하나를 로드 했습니다. 한 클러스터(Cluster-A)는 oltp_update_non_index.lua 워크로드를 실행하여 보조(Secondary) 인덱스로 포함되지 않은 컬럼을 업데이트하고 있고 다른 클러스터(Cluster-B)는 oltp_update_index.lua 워크로드를 실행하여 보조(Secondary) 인덱스가 생성된 컬럼을 업데이트합니다. 두 Sysbench 워크로드는 –rate를 사용하여 동일한 속도로 트랜잭션을 생성합니다.

이를 통해 아래와 같은 내용을 관찰할 수 있습니다.

  • DMLThroughput은 두 클러스터에서 동일한 패턴을 보여 주고 있으며 비슷한 양의 UPDATE 문이 실행되고 있음을 알 수 있습니다.
  • RollbackSegmentHistoryListLength는 oltp_update_index.lua 워크로드를 실행하는 클러스터에서 피크 시점에 300만 개를 넘습니다. 그러나 다른 클러스터에서는 0에 가깝게 유지됩니다. 이는 보조(Secondary) 인덱스가 포함된 언두 로그를 처리할 때 purge 스레드가 상당히 느려질 수 있음을 보여줍니다. 보조 인덱스를 사용하는 것이 반드시 문제가 되는 것은 아닙니다. 두 클러스터 모두 동일한 테이블 구조를 가지고 있으며 두 테이블에 모두 보조 인덱스가 있습니다. 보조 인덱스는 데이터베이스 워크로드에 의해 수정될 때만 purge 스레드에 문제를 일으킵니다.
  • 11:52분의 수직선은 클러스터 B에서 보조 인덱스(Secondary Index) 를 삭제한 시점을 보여줍니다. 보조 인덱스를 삭제하면 purge가 더 이상 보조 인덱스에서 레코드를 찾아 정리할 필요가 없기 때문에 purge 작업 속도가 즉각적으로 빨라집니다. 보조 인덱스를 삭제한 후 몇 분 만에 RollbackSegmentHistoryListLength가 0으로 떨어지는 것을 확인할 수 있습니다. SYS 스키마의 schema_unused_indexes 뷰를 사용하여 사용되지 않는 보조 인덱스를 식별하고 실제로 필요한지를 평가할 수 있습니다.

MySQL 8.0부터 purge Worker 스레드는 삭제 표시된 테이블 레코드를 정리할 때 여러 테이블에서 병렬로 작동하도록 설계되었습니다. 병렬 처리의 효율성은 몇 가지 요인에 따라 달라집니다. 다음 그래프는 purge worker 스레드 수와 Purge 대기 중인 언두 로그가 있는 테이블 갯수 간의 상관 관계를 보여주고 있습니다.

데이터는 이전 두개의 Aurora MySQL DB 클러스터의 다른 테스트에서 수집되었습니다. 한 클러스터(Cluster-A)는 80GB 사이즈의 하나의 테이블을 계속 사용하고 다른 클러스터(Cluster-B)는 각각 8GB 사이즈의 10개 테이블로 분산된 총 80GB 데이터를 가집니다. 두 클러스터 모두 Sysbench oltp_update_index.lua 워크로드를 실행하고 –rate를 사용하여 동일한 속도로 트랜잭션을 생성했습니다. 두 클러스터의 DB 인스턴스가 r7g.2xlarge이기 때문에 innodb_purge_threads는 디폴트로 3으로 설정됩니다. 즉 두 개의 purge worker 스레드(외 purge 코디네이터)가 동시에 실행될 수 있습니다.

이를 통해 아래와 같은 내용을 관찰할 수 있습니다.

  • DMLThroughput은 두 클러스터에서 동일한 패턴을 보여 비슷한 수의 UPDATE 문을 실행함을 나타냅니다.
  • RollbackSegmentHistoryListLength는 10개의 테이블이 있는 클러스터 B에서 피크 시간에 약 500K에 도달하는 반면, 1개의 테이블로 로드된 클러스터 A에서는 300만 개에 도달합니다. 더 빠른 purge 속도는 두 가지 요인에서 비롯됩니다. 두 개의 worker 스레드가 병렬로 작업하고 각 worker 스레드가 작업할 수 있는 테이블 크기가 작습니다. 한 번에 하나의 worker 스레드만이 하나의 테이블을 purge할 수 있습니다. 병렬성을 최대한 활용하려면 데이터 변경 사항을 purge 하는 worker 스레드보다 더 많거나 같은 수의 테이블에 균등하게 분산하는 것이 이상적입니다.
  • innodb_purge_threads는 purge 작업 속도에 영향을 주는 설정입니다. 다른 요인이 작용할 때 purge 스레드를 빠르게 진행하는 데 도움이 될 수 있습니다.

 

올바른 인스턴스 클래스 선택

Purge는 설계상 비간섭적인 기능입니다. purge 스레드는 백그라운드에서 실행되며 사용자 트랜잭션과 비동기식으로 작동합니다. 이는 적절한 지연 시간 내에 작업을 완료하기 위해 가능한한 최소한의 시스템 리소스를 소모할 것으로 예상합니다. MySQL은 innodb_purge_threads의 최대값을 32로 정의합니다. 즉, MySQL 데이터베이스에서 최대 32개의 purge 스레드를 구성할 수 있습니다. 이러한 설정은 수천 개의 동시 사용자 연결이 빈번한 프로덕션 데이터베이스에서 max_connections 임계치와 비교할 때 purge 스레드에 경쟁 우위를 제공하기 위한 것이 아닙니다.

purge 스레드가 언두 로그 또는 삭제 표시된 테이블 레코드를 처리할 때 InnoDB 버퍼 풀의 언두 로그 페이지와 데이터 페이지에서 데이터를 읽어야 합니다. 해당 데이터 페이지가 버퍼 풀에 없으면 I/O 호출을 실행하여 스토리지로부터 가져옵니다. RDS DB 인스턴스의 CPU, 메모리, IO 대역폭과 같은 시스템 리소스는 purge 작업 속도에 상당한 영향을 미칠 수 있습니다.

고속 purge 작업에는 purge 스레드 뿐만 아니라 전체 데이터베이스 워크로드에 대한 용량 계획도 필요합니다. 리소스가 부족하거나 사용자 트랜잭션에서 시스템 리소스가 많이 사용되는 DB 인스턴스에서 리소스 경합으로 인해 purge 스레드가 느려지고 purge 지연이 예상치 못한 것으로 나타날 수 있습니다. 다음 그래프는 r7g.2xlarge에 기본(Writer) DB 인스턴스가 있는 Aurora MySQL DB 클러스터에서 수행한 테스트에서 가져온 것으로, 이러한 유형의 상황의 예를 보여줍니다.

테스트는 두 개의 다른 Sysbench 데이터 세트를 순서대로 로드하는 것으로 시작합니다. 먼저 클러스터에 각각 8GB 데이터가 있는 10개의 Sysbench 테이블을 로드하고, 두 번째로 34GB 데이터가 있는 다른 테이블을 로드합니다. 데이터 로드 후 테스트는 34GB 테이블에 대해 oltp_read_only.lua 워크로드를 실행합니다. 이 34GB 테이블 데이터는 innodb_buffer_pool_size가 디폴트로 42GB로 설정되어 있기 때문에 InnoDB 버퍼 풀에 완전히 캐시 됩니다. 동시에 다른 10개 테이블의 대부분 데이터는 버퍼 풀에서 제거됩니다. 읽기 전용 작업이 완료되기 전에 테스트는 다른 10개 테이블에서 oltp_update_index.lua 작업을 시작합니다.

이를 통해 아래와 같은 내용을 관찰할 수 있습니다.

  • SelectThroughput과 DMLThroughput은 두 가지 다른 유형의 워크로드가 InnoDB 버퍼 풀에서 각자의 데이터 셋을 로딩하기 위해 서로 경쟁한다는 것을 보여줍니다.
  • RollbackSegmentHistoryListLength는 oltp_update_index.lua 워크로드가 끝날 때 500만 이상에 도달하는데 이는 이전 테스트와 비교할 때 예상치 못한 일입니다. 해당 테스트에서 동일한 oltp_update_index.lua 워크로드를 더 높은 속도(15K 대 10K)로 실행했고 약 320만의 최대 RollbackSegmentHistoryListLength 값에 도달했습니다.
  • BufferCacheHitRatio는 버퍼 풀에서 경합으로 인해 oltp_update_index.lua 워크로드가 시작될 때 급격히 떨어집니다. 워크로드가 완료된 후에도 계속 낮은 수준을 유지하는데 이는 purge 스레드가 언두 로그나 테이블 레코드를 버퍼 풀로 가져올 때 I/O 과정에서 병목 현상이 발생했음을 나타냅니다.
  • InnoDB 버퍼 풀에 대한 적절한 메모리 할당은 purge 작업 속도에 상당한 영향을 미칠 수 있습니다. 필요한 언두 로그나 테이블 데이터가 버퍼 풀에 없는 경우 purge 스레드의 성능은 IO 대기 시간과 밀접한 상관 관계가 있습니다.

MySQL 데이터베이스에서 innodb_purge_threads 파라미터를 변경하여 purge 스레드 개수를 설정할 수 있습니다. RDS for MySQL을 사용하는 경우 디폴트 값은 MySQL Community Edition과 동일한 1이며 DB 파라미터 그룹에서 변경할 수 있습니다. Aurora MySQL을 사용하는 경우 디폴트 값은 DB 인스턴스 크기가 늘어남에 따라 증가되는 공식이며 클러스터 파라미터 그룹에서 변경할 수 있습니다. 다음 테이블에서는 r7g 인스턴스 유형의 디폴트 공식을 기반으로 한 purge 관련 설정의 유효한 값을 보여주고 있습니다.

RDS instance type vCPU Memory (GiB) innodb_buffer_pool_size (GiB) innodb_purge_threads innodb_purge_batch_size
db.r7g.large 2 16 7.76 1 600
db.r7g.xlarge 4 32 19.36 1 600
db.r7g.2xlarge 8 64 42.59 3 1800
db.r7g.4xlarge 16 128 89.11 3 1800
db.r7g.8xlarge 32 256 182.06 6 3600
db.r7g.12xlarge 48 384 275.11 12 7200
db.r7g.16xlarge 64 512 368.13 12 20000

Aurora Serverless v2 인스턴스 유형의 경우 이 설정은 인스턴스가 확장되거나 축소될 때 자동으로 구성되며 파라미터 그룹에서 수정할 수 없습니다.

모니터링 알람

InnoDB purge를 모니터링하는데 유용한 메트릭은 Rollback history list length (purge 지연이라고도 함)이며 이는 purge를 기다리는 언두 로그의 수를 나타냅니다. MySQL 데이터베이스에서 SHOW ENGINE INNODB STATUS를 실행하여 히스토리 리스트 길이(History List Length)를 직접 확인할 수 있습니다. Aurora MySQL은 3.0 릴리즈부터 RollbackSegmentHistoryListLength를 CloudWatch 메트릭으로 제공하기 시작했습니다. Amazon RDS for MySQL은 Performance Insights에서 메트릭 trx_rseg_history_len값을 제공하며 CloudWatch에 이를 게시할 수 있습니다.

이 메트릭에 CloudWatch 알람을 설정하여 purge 지연이 발생되어 데이터베이스 성능 문제가 일어나는 것을 감지하는 것이 좋습니다. 데이터베이스가 이전 발생 범위 내의 정상 값의 이력과 알람이 트리거될 때 수행할 작업 항목을 기반으로 알람 임계값을 설정할 수 있습니다.

데이터베이스 워크로드로 인해 purge 스레드가 충분히 빠르게 처리할 수 없을 정도로 많은 언두 로그가 생성되어 purge 지연이 너무 높은 경우 데이터베이스 인스턴스의 크기를 늘려 purge 스레드에 더 많은 리소스 할당이 가능하도록 합니다. 또는 데이터베이스 샤딩(sharding) 아키텍처를 사용하여 워크로드를 여러 데이터베이스 샤드에 분산할 수 있습니다. 또한 MySQL은 innodb_max_purge_lag를 제공하여 롤백 세그먼트 히스토리 리스트의 길이에 대한 임계값을 설정할 수 있습니다. 초과되면 INSERT, DELETE, UPDATE 문에 대해 최대 innodb_max_purge_lag_delay까지 최대 지연을 허용하는 파라미터를 통해 내부 제한을 적용할 수 있습니다. 이런 설정을 테스트하면서 사용 사례에 가장 적합한 옵션을 확인할 수 있습니다.

요약

InnoDB purge 효율성을 개선하려면 워크로드 최적화, 데이터베이스 용량 계획과 구성을 같이 고려 해야 합니다. 지금까지 RDS for MySQL DB 인스턴스, Aurora MySQL DB 클러스터와 다른 종류의 MySQL 데이터베이스에서 이를 수행하는 데 도움이 되는 가이드를 설명 드렸습니다.

Dokeun Kim

Dokeun Kim

김도근 Cloud Support DB Expert는 Amazon Database 서비스에 대한 고객들의 기술적 문의 및 이슈 분석 등의 고객지원 업무를 수행하고 있습니다.