AWS 기술 블로그

Amazon Aurora MySQL 버전 2(MySQL 5.7 호환)에서 버전 3(MySQL 8.0 호환)으로 업그레이드 체크리스트, 2부

이 글은 AWS Database Delivery Blog에 게시된 Amazon Aurora MySQL version 2 (with MySQL 5.7 compatibility) to version 3 (with MySQL 8.0 compatibility) upgrade checklist, Part 2 by Huy Nguyen and Leevon Abuan 을 한국어 번역 및 편집하였습니다.

1부에서는 Amazon Aurora MySQL 호환 버전 v2에서 v3으로의 업그레이드 사전 확인이 실패하는 가장 일반적인 문제에 대해 논의했습니다. 이 글에서는 장기간 지속되거나 업그레이드가 실패하는 가장 일반적인 원인에 대해 논의합니다.

클러스터에 준비된(prepared) 상태의 XA 트랜잭션이 있습니다.

Amazon Aurora MySQL은 업그레이드 중 데이터베이스에서 준비 상태의 XA 트랜잭션을 감지하면 업그레이드를 취소합니다. 데이터베이스를 장애 조치하거나 재부팅해도 준비된 XA 트랜잭션은 제거되지 않습니다. 업그레이드하기 전에 준비된 XA 트랜잭션을 검색한 후 커밋하거나 롤백해야 합니다. 다음 코드는 방법을 보여주는 간단한 예입니다.

세션을 열고 XA 트랜잭션을 시작한 다음 세션을 닫습니다.

mysql> USE sakila;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed

mysql> XA START 'gtridtest','bqualtest',123456;
Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE actor SET first_name='testname' WHERE actor_id=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> XA END 'gtridtest','bqualtest',123456;
Query OK, 0 rows affected (0.00 sec)

mysql> XA PREPARE 'gtridtest','bqualtest',123456;
Query OK, 0 rows affected (0.00 sec)

mysql> exit;

xid는 XA 트랜잭션 식별자입니다. 명령문이 어떤 트랜잭션에 적용되는지를 나타냅니다. xid 값은 클라이언트에서 제공되거나 MySQL 서버에서 생성됩니다. xid 값은 gtrid [, bqual [, formatID]]의 1 부터 3의 부분으로 구성됩니다. gtrid는 전역 트랜잭션 식별자이고, bqual은 분기 한정자이며, formatIDgtridbqual 값에 사용되는 형식을 식별하는 숫자입니다. bqualformatID는 선택 사항입니다. 지정되지 않은 경우 기본 bqual 값은 ‘ ‘입니다. 지정되지 않은 경우 기본 formatID 값은 1입니다.

지금 시점에 데이터베이스에 준비된 XA 트랜잭션이 있습니다. 다음 명령은 준비된 XA 트랜잭션을 검색합니다.

mysql> XA RECOVER CONVERT xid;
+----------+--------------+--------------+----------------------------------------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+----------------------------------------+
| 123456 | 9 | 9 | 0x677472696474657374627175616C74657374 |
+----------+--------------+--------------+----------------------------------------+
1 row in set (0.00 sec)

출력 열의 의미는 다음과 같습니다.

  • formatID는 트랜잭션 xidformatID 부분입니다.
  • gtrid_lengthxidgtrid 부분 길이(바이트)입니다.
  • bqual_lengthxidbqual 부분의 길이(바이트)입니다.
  • data는 xidgtridbqual 부분을 연결한 것입니다.

이 값을 사용하여 데이터 필드의 다음 부분을 추출할 수 있습니다.

  • gtrid = 0x677472696474657374
  • bqual = 0x627175616C74657374

롤백하려면 XA ROLLBACK 명령을 사용합니다.

mysql> XA ROLLBACK 0x677472696474657374,0x627175616C74657374,123456;
Query OK, 0 rows affected (0.01 sec)

클러스터에 상당한 수의 테이블이 있습니다.

Aurora MySQL은 공개 문서에 설명된 대로 여러 단계의 프로세스로 메이저 버전 업그레이드를 수행합니다. 클러스터에 테이블 수가 많으면 딕셔너리 확인 및 엔진 버전 업그레이드 단계의 기간이 연장될 수 있습니다. 엔진 버전 업그레이드 단계는 데이터 딕셔너리 업그레이드와 서버 업그레이드의 2단계로 진행됩니다.

MySQL 8.0과 MySQL 5.7 은 MySQL 데이터 딕셔너리가 저장되는 방식에 큰 변화가 있습니다. MySQL 5.7 이하에서는 MySQL 딕셔너리 데이터가 데이터 파일(.frm 파일, .par 파일, .trn 파일)에 저장되었습니다. 예를 들어 기본값인 innodb_file_per_table =1인 경우 각 InnoDB 테이블에는 자체 .frm 파일이 있습니다. 그러나 MySQL 8.0에서는 MySQL 딕셔너리 데이터가 mysql 스키마의 테이블에 중앙에 저장됩니다. 이는 MySQL 설명서에서 확인하실 수 있습니다. 위의 데이터 딕셔너리 업그레이드 단계에서 서버는 업데이트된 정의로 데이터 딕셔너리 테이블을 생성하고, 유지된 메타데이터를 새 테이블에 복사하고, 이전 테이블을 새 테이블로 원자적으로 교체하고, 데이터 딕셔너리를 다시 초기화합니다. 따라서 클러스터에 많은 수의 테이블이 포함된 경우 수많은 메타데이터 파일을 제거하고 테이블로 마이그레이션하면 전체 업그레이드 기간이 연장될 수 있습니다. Amazon Aurora MySQL 버전 업그레이드도 매우 유사한 방식으로 진행되므로 테이블 수가 많을 때의 영향 부분도 적용됩니다.

서버 업그레이드 단계에서 서버는 필요에 따라 사용자 스키마의 테이블을 처리합니다. 문제가 발견되면 테이블을 확인하고 복구를 시도합니다. 이는 클러스터에 테이블이 많으면, 특히 대규모 테이블의 경우 시간이 많이 걸릴 수 있습니다.

버전2에서 버전3으로 업그레이드하는 동안 테이블 수가 많아지는 영향을 완화하려면 백업 테이블, 이전 테이블 파티션 등 사용하지 않는 테이블을 검토하고 제거하는 것이 좋습니다. 상당한 수의 테이블이 포함된 클러스터의 주요 버전을 업그레이드하는 것은 리소스 집약적일 수 있으며 잠재적으로 일일 작업량을 초과할 수 있습니다. 테스트 업그레이드 중에 리소스 경합이 발생하는 경우 프로덕션 인스턴스 클래스를 일시적으로 확장하고 업그레이드가 완료되면 다시 축소하는 것을 고려하세요. CPU 경합 확인을 위해 CPUUtilization, 메모리 압력 확인을 위해 FreeableMemorySwapUsage, 인스턴스 처리량을 확인을 위한 NetworkThroughputStorageNetworkThroughput 등 주요 Amazon CloudWatch 지표를 모니터링해야 합니다. 다음 쿼리를 실행하여 클러스터의 테이블 수를 가져올 수 있습니다.

SELECT count(*) AS TOTAL_NUMBER_OF_TABLES FROM INFORMATION_SCHEMA.TABLES;

실제 프로덕션 로드가 있는 다수의 테이블이 있는 프로덕션 인스턴스에서 이 쿼리를 실행하면 시간이 오래 걸리고 데이터베이스 성능이 저하될 수 있으므로 프로덕션에 미치는 영향을 최소화하기 위해 복제된 클러스터에서 실행하는 것이 좋습니다.

클러스터에 undo 레코드 수가 많습니다.

In-place 업그레이드 메커니즘에는 작업이 진행되는 동안 DB 클러스터를 종료하는 작업이 포함됩니다. Amazon Aurora MySQL은 완전한 종료를 수행하고 undo purge와 같은 미해결 작업을 완료합니다. RDS 블루/그린 배포 및 스냅샷 복원 방법을 사용하더라도 제거할 undo 레코드 수가 많으면 업그레이드하는 데 시간이 오래 걸릴 수 있습니다.

클러스터 쓰기 인스턴스의 Amazon Aurora MySQL CloudWatch 지표 RollbackSegmentHistoryListLength(HLL) 값은 다중 버전 동시성 제어(MVCC)를 구현하기 위해 데이터베이스에 저장된 undo 레코드 수를 나타냅니다. SHOW ENIGNE INNODB STATUS를 실행하고 TRANSACTIONS 섹션에서 History list length 값을 찾을 수도 있습니다. 기록 목록 길이가 짧아진 후에만 업그레이드를 수행하는 것을 고려하십시오. 일반적으로 허용되는 내역 목록 길이 값은 100,000 이하입니다. 그러나 HLL의 중단 속도는 애플리케이션 워크로드, 스키마 속성, 인스턴스 클러스터 구성 등 여러 요소에 따라 달라집니다. 높은 HLL 문제를 해결해야 하는 경우 Amazon Aurora MySQL DB 클러스터에서 SELECT 쿼리가 느리게 실행되는 이유는 무엇일까요?, InnoDB history list length가 크게 증가함 및 Purge 구성을 참조하십시오. Amazon RDS 블루/그린 배포를 사용하여 높은 HLL 문제를 해결할 수도 있습니다. 그린 클러스터의 업그레이드 시간이 줄어들지는 않지만 애플리케이션 가동 중지 시간을 최소화하는 데 도움이 됩니다. 그러나 장기간의 업그레이드로 인해 녹색 클러스터를 따라잡는 데 시간이 더 오래 걸릴 수 있습니다.

클러스터에 진행 중인 대규모 쓰기 트랜잭션이 있습니다(많은 행에 대해 커밋되지 않은 변경 사항).

Undo purge와 유사하게 트랜잭션 롤백은 완전 종료 중에 발생하므로 롤백할 행이 많으면 업그레이드가 길어질 수 있습니다. 불완전한 트랜잭션을 롤백하는 데 걸리는 시간은 서버 로드에 따라 트랜잭션이 중단되기 전에 활성화된 시간의 3배 또는 4배가 될 수 있습니다. 롤백 시간을 예측하는 쉬운 방법은 없습니다. 롤백 중인 트랜잭션은 취소할 수 없습니다. 단순히 데이터베이스를 다시 시작하거나 클러스터를 장애 조치하는 것은 트랜잭션 롤백 속도를 높이는 데 도움이 되지 않으며 일부 데이터가 디스크에서 메모리로 다시 로드되는 경우 경우에 따라 속도가 느려질 수 있습니다.

따라서 업그레이드를 진행하기 전에 다음 쿼리를 실행하여 커밋되지 않은 총 행 수를 확인해야 합니다.

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX ORDER BY TRX_ROWS_MODIFIED DESC;

테이블에는 각 트랜잭션에 대해 하나의 행이 포함됩니다. TRX_ROWS_MODIFIED 열에는 트랜잭션에 의해 수정되거나 삽입된 행 수가 포함됩니다. 모든 대규모 트랜잭션이 커밋되거나 롤백된 후에만 업그레이드를 수행하는 것이 좋습니다.

클러스터에 장기 실행 또는 커밋되지 않은 유휴 트랜잭션이 있습니다.

읽기 전용 또는 읽기-쓰기 장기 실행 트랜잭션 또는 커밋되지 않은 유휴 트랜잭션은 테이블 잠금을 유지하여 업그레이드 사전 확인이 완료되지 않도록 차단할 수 있습니다. 결과적으로 업그레이드가 매우 오래 걸리거나 심지어 중단된 것처럼 보일 수도 있습니다. select * from information_schema.processlist where USER='rdsadmin'를 실행하면 FLUSH LOCAL TABLE 명령이 Waiting for table flush 상태에서 대기 중이거나 CHECK TABLE 명령이 Waiting for table metadata lock 상태에서 대기 중인 것을 볼 수 있습니다. 이 경우 다음 쿼리를 사용하여 차단 트랜잭션을 식별하고 가능하면 그에 따라 커밋, 롤백 또는 종료할 수 있습니다.

SELECT * FROM information_schema.innodb_trx\G
SELECT * FROM information_schema.processlist where id=<# trx_mysql_thread_id from innodb_trx table above>;
CALL mysql.rds_kill(#id from processlist table above);

이 문제를 극복하려면 업그레이드 프로세스를 시작하기 전에 장기 실행 또는 커밋되지 않은 유휴 트랜잭션을 식별하십시오. 다음 쿼리를 실행하면 됩니다.

SELECT a.trx_id,a.trx_state,a.trx_started,
TIMESTAMPDIFF(SECOND, a.trx_started, now()) as "Seconds Transaction Has Been Open",
a.trx_rows_modified,b.id,b.USER,b.host,b.db,b.command,b.time,b.state

from
information_schema.innodb_trx a,information_schema.processlist b

where
a.trx_mysql_thread_id = b.idorder bytrx_started;

그런 다음 완료될 때까지 기다리거나 가능하다면 kill 문으로 종료합니다. 대규모 쓰기 트랜잭션을 종료하면 위 섹션에서 언급한 것처럼 롤백하는 데 오랜 시간이 걸릴 수 있습니다.

CALL mysql.rds_kill(#id from processlist table above);

동일한 쿼리를 사용하여 클러스터가 데이터 정의 언어(DDL) 문을 처리하고 있는지 확인할 수 있습니다. 모든 DDL 문(CREATE, DROP, ALTER, RENAME, and TRUNCATE)이 완료된 후에 업그레이드를 수행해야 합니다. 그렇지 않으면 Amazon Aurora MySQL이 업그레이드를 취소합니다. 관련 테이블에 대한 데이터 딕셔너리 불일치 문제가 발생할 수 있으므로 실행 중인 DDL을 중단하는 것은 권장되지 않습니다.

결론

이글에서는 업그레이드가 지연되고 실패하는 가장 일반적인 원인에 대해 논의했습니다. Amazon Aurora MySQL 2 버전이 2024년 10월 31일에 수명이 종료됨에 따라, Aurora MySQL 3 버전에서 사용할 수 있는 최신 기능과 최적화를 활용하려면 최대한 빠른 시일 내에 Aurora MySQL 2 버전 클러스터를 Aurora MySQL 3 버전의 기본 마이너 버전 이상으로 업그레이드하는 것이 좋습니다.

Yujin Cho

Yujin Cho

조유진 테크니컬 어카운트 매니저는 다양한 데이터베이스의 운영과 데이터 분석 경험을 바탕으로 고객이 데이터 기반의 비즈니스 목표를 달성할 수 있도록 고객과 함께 효율적인 아키텍처와 안정적인 운영 환경을 구성하기 위해 노력하고 있습니다.