Amazon Aurora Mysql을 실제 사용하며 발생한 과금 정책을 파악한 내용입니다.
(POC용 클러스터로 2GB의 매우 작은 Storage 이용중)
+ Aurora MySQL의 DB 스토리지 사용량이 예상보다 큰 경우의 문제해결 과정이 포함되어 있습니다.
0. 사용하는 DB 인스턴스 스펙
Tier | db.t3.small(2vCPU, 2GB RAM) |
Version | mysql 5.6.10a |
Region | Seoul |
1. 요금 분류 - Amazon Aurora Storage and I/O
-
USD 0.12 per GB-month of consumed storage for Aurora MySQL
-> Aurora의 가상화 계층에서 사용하는 스토리지의 용량이 아닌 DB 계층에서 사용한 스토리지를 기준
(간단하게 정리하면, DB의 사용량에 대해 물리적 사용 공간이 아닌 논리적 사용공간을 의미) -
USD 0.24 per 1 million I/O requests for Aurora MySQL
-> 1백만 I/O당 0.24$
2. 요금 분류 - Amazon Relational Database Service for Aurora MySQL
-
USD 0.023 per GB-month of backup storage exceeding free allocation for Aurora MySQL
-> Backup Storage의 무료 할당 용량을 초과하는 GB당 과금 -
USD 0.063 per db.t3.small Single-AZ instance hour (or partial hour) running Aurora MySQL
-> Instance Tier에 따른 Instance 구동 시간
3. Aurora MySQL - 예상보다 큰 Storage를 사용하는 경우의 문제해결
Aurora MySQL 요금 기준에서 GB-month of consumed storage for Aurora MySQL(Aurora MySQL 스토리지 사용량)에 대해서는 명확한 기준을 파악하기 어려웠다. 분명히 DB에서 사용하는 스토리지는 2GB(MySQL WorkBench 상 표기되는 용량) 남짓밖에 안 되는데 요금에는 스토리지 사용량이 15GB가 나온 것이다.(실제 Storage 사용 용량 15GB는 CloudWatch의 VolumeBytesUsed 지표와 거의 일치)
찾아본 결과 아래 과금정책이 운용됨을 확인하였다.
1) Aurora 클러스터 볼륨은 최대 64 TiB까지 증가할 수 있지만 요금은 Aurora 클러스터 볼륨에서 사용한 공간에 대해서만 청구됩니다. 테이블 또는 파티션을 삭제하는 등으로 Aurora 데이터가 제거될 때 전체 할당 공간은 동일하게 유지됩니다. 사용 가능한 공간은 향후에 데이터 볼륨이 증가할 때 자동으로 재사용됩니다.
2) Aurora 클러스터에서 데이터를 제거하면 많은 양이 할당되었지만 사용되지 않은 공간이 발생하는 경우 하이 워터 마크를 재설정할 때 mysqldump과 같은 도구를 사용하여 논리적 데이터 덤프를 수행하고 새 클러스터로 복원해야 합니다. 스냅샷을 생성하고 복원하면 기본 스토리지의 물리적 레이아웃이 복원된 스냅샷에서 동일하게 유지되기 때문에 할당된 스토리지가 감소하지 않습니다.
출처: https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.StorageReliability.html
즉, DB 클러스터의 전체 볼륨에서의 사용을 의미한다. mysql DB를 사용하면서 여러 작업을 하게 된다.(테이블을 만들었다 지웠다, 조회하거나, Insert 하거나 등등) 이 과정에서 Storage 사용량은 계속 증가한다. 증가하게 되는 가장 큰 원인은 3-2에서 상세하게 기술할 예정. 우선은 위 정책과 같이 테이블 또는 데이터가 제거돼도, 전체 할당 공간은 동일하게 유지된다는 내용만 확인하자.
그리고 2)의 내용과 같이 공식문서에서는 사용되지 않은 공간이 발생하면, mysql dump를 활용해 새 클러스터의 복원을 추천한다. 그렇지만, DB 사이즈가 매우 커서 번거롭거나 dump 할 환경이 안 될 수도 있다. 그래서 dump 없이 storage를 줄이기 위한 방법을 시도해 보았다.
3-1 디스크를 점유하는 실제 용량 확인
SELECT
table_schema,
SUM(data_length + index_length + data_free)/1024/1024/1024 AS total_GB,
SUM(data_length)/1024/1024/1024 AS data_GB,
SUM(index_length)/1024/1024/1024 AS index_GB,
SUM(data_free)/1024/1024/1024 AS free_GB,
COUNT(*) AS tables,
CURDATE() AS today
FROM information_schema.tables
GROUP BY table_schema
ORDER BY 2 DESC ;
위 쿼리 조회로 현재 DB 클러스터에서 점유하는 실제 Size를 파악할 수 있다. 확인하니 DataBase 중 mysql의 free 영역의 사용량이 상대적으로 매우 높았다.
3-2 'OPTIMIZE TABLE'을 사용하여 free 영역 rebuild 하는 것에 대해
OPTIMIZE TABLE을 사용하려는 이유는 다음과 같다. Aurora MySQL의 5.6 version의 innodb_file_per_table 설정 Default 값은 1(ON)이다. 이 설정이 켜져 있으면 개별 테이블이 각각의 파일로 저장된다. 아래는 각 테이블이 어떤 Table Sapce(테이블 스페이스)에 기록되는지 확인하기 위한 쿼리이다.
SELECT name, space FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES;
테이블이 생성될 때, 이렇게 각 Table Space가 만들어지고 이를 삭제하면 Free Space로 남는 것이다. 그리고 이렇게 빈 공간인 채로 데이터 사이즈만 차지하는 현상을 단편화(Fragmentation)이라고 한다.
결국 자꾸만 커지는 이 free 영역의 데이터를 줄이려면 Windows의 디스크 조각모음과 같은 Defragmentation(단편화 제거)를 해야 한다. 그리고 이 기능을 수행하는 것이 OPTIMIZE TABLE이다.
그런데 Aurora MySQL에서 OPTIMIZE TABLE로 Table Space(free 영역)를 삭제하여 용량을 줄이는 것이 불가능하다. 원인은 Aurora MySQL의 성능과 Fault Tolerance의 향상을 위해 독특한 구조로 되어 있기 때문이다.
이런 상황에서 OPTIMIZE TABLE을 강제로 사용한다면 어떻게 될까? 결론부터 얘기하면 오히려 클러스터의 용량이 증가한다. OPTIMIZE TABLE을 사용하면 테이블의 재구성이 발생한다. 인덱스 통계를 업데이트하는 등의 작업을 통해 또 다른 Table Space를 만들기 때문이다. 실제로 700MB 정도의 테이블에 대해 'OPTIMIZE TABLE'을 실행하였는데, 용량이 오히려 200MB 늘었다.(CloudWatch의 VolumeBytesUsed 기준)
문제해결의 측면에서 보면, 제대로 된 해결이 어렵다는 것만 확인하였다. 처음에 언급했던 mysql dump 후, 새로운 인스턴스에 복원시키는 게 가장 직접적인 해결이다.
요약
- Aurora MySQL의 구조 때문에 OPTIMIZE TABLE 명령어로 단편화된 free 영역의 재사용이 불가능하다.
3-4 결론
Aurora MySQL이 AWS 제공되는 RDS 중 가격과 성능면에서 장점이 있다. 그러나 이 성능을 높이기 위한 DB 인스턴스 구조로 용량 부분에서 다소 불편함을 느낄 수도 있다고 생각한다. 개발 목적에 맞게 RDS를 선택할 수 있기 때문에 장단을 잘 파악하여 활용하는 게 필요하다.
참조한 글
https://serverfault.com/questions/873699/why-is-my-volume-bytes-used-always-increasing-on-my-amazon-aurora-cluster
-> 이 글을 작성하게 된 동기이기도 하다. AWS의 공식문서는 아니지만 충분히 읽을 가치가 있다.