OS 접근이 불가능할 때 대략적인 데이터파일 사이즈 계산하기 (MySQL)

DB가 설치되어 있는 OS에 직접 접속이 불가능할 때, 대략적인 데이터파일 사이즈 확인 법

MySQL 데이터파일 사이즈 계산
Overlay Image Overlay Image
MySQL 데이터파일 사이즈 계산

OS에서 MySQL 데이터파일 사이즈 계산하기

MySQL 계열의 DBMS에서 현재 사용중인 데이터 파일의 총 사이즈를 계산하기 가장 쉬운 방법은 datadir에 이동하여 실제 데이터 파일의 사용량을 확인해보는 것일 겁니다. 그럼 MySQL 데이터파일 사이즈 계산에 대한 방법을 알아보겠습니다.

[mysql@MySQL8032 ~]$ cd /data/datadir
[mysql@MySQL8032 datadir]$ ls -lh
total 179M
-rw-r----- 1 mysql mysql 576K Nov  9 12:35 #ib_16384_0.dblwr
-rw-r----- 1 mysql mysql 8.6M Apr  4  2024 #ib_16384_1.dblwr
drwxr-x--- 2 mysql mysql 4.0K Nov  8 13:12 #innodb_redo
drwxr-x--- 2 mysql mysql  231 Nov  8 13:12 #innodb_temp
-rw-r----- 1 mysql mysql    4 Nov  8 13:12 MySQL8032.pid
-rw-r----- 1 mysql mysql   56 Dec 10  2023 auto.cnf
-rw------- 1 mysql mysql 1.7K Dec 10  2023 ca-key.pem
-rw-r--r-- 1 mysql mysql 1.1K Dec 10  2023 ca.pem
-rw-r--r-- 1 mysql mysql 1.1K Dec 10  2023 client-cert.pem
-rw------- 1 mysql mysql 1.7K Dec 10  2023 client-key.pem
drwxr-x--- 2 mysql mysql 4.0K Dec 10  2023 guacamole_db
-rw-r----- 1 mysql mysql 4.6K Dec 10  2023 ib_buffer_pool
-rw-r----- 1 mysql mysql 100M Nov  9 12:33 ibdata1
-rw-r----- 1 mysql mysql  12M Nov  8 13:12 ibtmp1
drwxr-x--- 2 mysql mysql  101 Apr  4  2024 minhang
drwxr-x--- 2 mysql mysql  143 Dec 10  2023 mysql
-rw-r----- 1 mysql mysql  25M Nov  9 04:07 mysql.ibd
drwxr-x--- 2 mysql mysql 8.0K Dec 10  2023 performance_schema
-rw------- 1 mysql mysql 1.7K Dec 10  2023 private_key.pem
-rw-r--r-- 1 mysql mysql  452 Dec 10  2023 public_key.pem
-rw-r--r-- 1 mysql mysql 1.1K Dec 10  2023 server-cert.pem
-rw------- 1 mysql mysql 1.7K Dec 10  2023 server-key.pem
drwxr-x--- 2 mysql mysql   36 Dec 10  2023 sys
-rw-r----- 1 mysql mysql  16M Nov  9 12:35 undo_001
-rw-r----- 1 mysql mysql  16M Nov  9 04:07 undo_002
[mysql@MySQL8032 datadir]$ du -sh .
459M    .
[mysql@MySQL8032 datadir]$ cd guacamole_db/
[mysql@MySQL8032 guacamole_db]$ ls -lh
total 3.1M
-rw-r----- 1 mysql mysql 144K Jul  5 04:37 guacamole_connection.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_connection_attribute.ibd
-rw-r----- 1 mysql mysql 144K Dec 10  2023 guacamole_connection_group.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_connection_group_attribute.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_connection_group_permission.ibd
-rw-r----- 1 mysql mysql 240K Nov  9 12:33 guacamole_connection_history.ibd
-rw-r----- 1 mysql mysql 112K Oct 15 17:47 guacamole_connection_parameter.ibd
-rw-r----- 1 mysql mysql 128K Jul  5 04:36 guacamole_connection_permission.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_entity.ibd
-rw-r----- 1 mysql mysql 144K Dec 10  2023 guacamole_sharing_profile.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_sharing_profile_attribute.ibd
-rw-r----- 1 mysql mysql 112K Dec 10  2023 guacamole_sharing_profile_parameter.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_sharing_profile_permission.ibd
-rw-r----- 1 mysql mysql 112K Dec 10  2023 guacamole_system_permission.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_user.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_user_attribute.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_user_group.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_user_group_attribute.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_user_group_member.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_user_group_permission.ibd
-rw-r----- 1 mysql mysql 176K Nov  9 03:31 guacamole_user_history.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_user_password_history.ibd
-rw-r----- 1 mysql mysql 128K Dec 10  2023 guacamole_user_permission.ibd

하지만 이와 같은 방법은 DB가 설치되어있는 서버에 접근이 가능할 경우에만 사용할 수 있기 때문에,
이를테면 AWS RDS와 같은 환경처럼 OS에 대한 접근이 불가능 환경이라거나,
DB 서버를 관리하는 주체가 DBA와 SE등으로 나뉘어 있어 승인등의 절차를 거치기 전에는 서버 접근이 제한적인 경우라면 위와 같은 방법을 적용하는데 한계가 있을 것입니다.

딕셔너리 쿼리 수행하여 데이터파일 사이즈 확인

이 경우 아래와 같은 쿼리를 통해 대략적인 사이즈를 간단히 구해볼 수 있습니다.

-- 테이블별 사이즈
SELECT 
    concat(table_schema,'.', table_name) AS `Table Name`,
    round(((data_length + index_length) / 1024 / 1024), 2) AS `Size (MB)`
FROM 
    information_schema.TABLES 
WHERE 
    table_schema not in ('sys', 'mysql', 'information_schema','performance_schema');

-- 전체 합계 사이즈
SELECT 
    round(sum(((data_length + index_length) / 1024 / 1024)),2) AS `Size (MB)`, round(sum(((data_length + index_length) / 1024 / 1024 / 1024)),2) AS `Size (GB)`
FROM 
    information_schema.TABLES 
WHERE 
    table_schema not in ('sys', 'mysql', 'information_schema','performance_schema');

(실행 예시)

mysql> SELECT 
    ->     concat(table_schema,'.', table_name) AS `Table Name`,
    ->     round(((data_length + index_length) / 1024 / 1024), 2) AS `Size (MB)`
    -> FROM 
    ->     information_schema.TABLES 
    -> WHERE 
    ->     table_schema not in ('sys', 'mysql', 'information_schema','performance_schema');
+------------------------------------------------------------+-----------+
| Table Name                                                 | Size (MB) |
+------------------------------------------------------------+-----------+
| bookstack.refe                                             |      0.02 |
| bookstack.api_tokens                                       |      0.06 |
| bookstack.bookshelves_books                                |      0.03 |
... 중략 ...
+------------------------------------------------------------+-----------+
204 rows in set (0.02 sec)

mysql> SELECT 
    ->     round(sum(((data_length + index_length) / 1024 / 1024)),2) AS `Size (MB)`, round(sum(((data_length + index_length) / 1024 / 1024 / 1024)),2) AS `Size (GB)`
    -> FROM 
    ->     information_schema.TABLES 
    -> WHERE 
    ->     table_schema not in ('sys', 'mysql', 'information_schema','performance_schema');
+-----------+-----------+
| Size (MB) | Size (GB) |
+-----------+-----------+
|    390.69 |      0.38 |
+-----------+-----------+
1 row in set (0.00 sec)

다만 이 경우 실제 OS에서 확인되는 디스크 사용량과는 다소의 차이가 발생합니다.

이 값은 테이블 통계 정보에만 의존해 테이블 사이즈가 대략 어느정도 될지 산술적으로 계산해 놓은 것입니다.
따라서,

  • 실제 정확히 지금 테이블이 몇 row인지, 가변형 데이터타입에 어느정도 데이터가 저장되어 있는지가 정확히 계산된 것은 아닙니다. → 그래서 실제로 저장되어있는 데이터가 몇 Bytes인지 계산이 맞지가 않습니다.
  • 또한 undo 영역이 사용하고 있는 부분이라거나, 각종 메타 정보, 한번 커졌다가 대량의 delete 이후로 반납되지 않은 디스크 공간 같은 부분이 포함되지 않습니다.

하여 실제 OS에서 디스크를 얼마나 잡아먹고 있는지와는 차이가 발생합니다.
상황에 따라서 이 차이가 매우 클 수도 있으므로, 대략적으로 ‘어떤 테이블이 비교적 매우 크구나’, ‘대략적인 사이즈가 수십기가 급이구나. 테라급 이상이구나’ 하는식의 형태 파악에나 활용 가능합니다.

결국에 OS상의 디스크 공간이 얼마나 사용되고 있고, 부족한지 확인하려면 OS에서 확인해 봐야합니다.
RDS나 Aurora에서 디스크 사용량으로 얼마나 가격이 측정되고 있는지에 참고하기도 어렵습니다.

AWS에서 볼륨 사용량 확인

만약 RDS에서 디스크 사용량을 확인해보려면 클라우드와치의 VolumeBytesUsed 지표를 참고하시면 되겠습니다.

콘솔에 접속하며 그래프 형태로 확인도 가능하며,

AWS RDS의 경우 클라우드와치의 VolumeBytesUsed 지표를 통해 MySQL 데이터파일 사이즈 계산

아래와 같은 형태로 aws cli 명령어를 사용해 확인할 수도 있습니다.
(aws cli를 사용하기 위한 credentials등은 미리 세팅되어 있어야 합니다.)

aws cloudwatch get-metric-statistics \
  --namespace "AWS/RDS" \
  --metric-name "VolumeBytesUsed" \
  --dimensions Name=DBClusterIdentifier,Value=클러스터-DB식별자 \
  --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "-1 hour") \
  --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") \
  --period 300 \
  --statistics Maximum \
  --region 사용중인리전 \
  --query "Datapoints | [-1]"

(실행 예시)

[root@MinhangHome ~]# aws cloudwatch get-metric-statistics \
>   --namespace "AWS/RDS" \
>   --metric-name "VolumeBytesUsed" \
>   --dimensions Name=DBClusterIdentifier,Value=minhangaurora \
>   --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "-1 hour") \
>   --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") \
>   --period 300 \
>   --statistics Maximum \
>   --region ap-northeast-2 \
>   --query "Datapoints | [-1]"
{
    "Timestamp": "2024-11-10T12:27:00+00:00",
    "Maximum": 1422458880.0,
    "Unit": "Bytes"
}

아래는 더 간편히 확인하기 위해 쉘 스크립트 형태로 만들어본 예시입니다.

#!/bin/bash
echo -n "DB식별자 : "
read DBNM

# AWS CLI를 사용해 가장 최신의 VolumeBytesUsed 메트릭을 가져와서 변수에 저장
LATEST_USAGE=$(aws cloudwatch get-metric-statistics \
  --namespace "AWS/RDS" \
  --metric-name "VolumeBytesUsed" \
  --dimensions Name=DBClusterIdentifier,Value="${DBNM}" \
  --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "-1 hour") \
  --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") \
  --period 300 \
  --statistics Maximum \
  --region ap-northeast-2 \
  --query "Datapoints[-1].Maximum" \
  --output text)

# LATEST_USAGE 값을 MB, GB, TB로 변환
LATEST_USAGE_MB=$(echo "$LATEST_USAGE / 1024 / 1024" | bc)
LATEST_USAGE_GB=$(echo "$LATEST_USAGE / 1024 / 1024 / 1024" | bc)
LATEST_USAGE_TB=$(echo "$LATEST_USAGE / 1024 / 1024 / 1024 / 1024" | bc)

# 결과 출력
echo "현재 사용 중인 스토리지 용량:"
echo "$LATEST_USAGE 바이트 (B)"
echo "$LATEST_USAGE_MB 메가바이트 (MB)"
echo "$LATEST_USAGE_GB 기가바이트 (GB)"
echo "$LATEST_USAGE_TB 테라바이트 (TB)"

(실행 예시)

[root@MinhangHome ~]# sh DBsize.sh 
DB식별자 : minhangaurora
현재 사용 중인 스토리지 용량:
1422458880.0 바이트 (B)
1356 메가바이트 (MB)
1 기가바이트 (GB)
0 테라바이트 (TB)

관련글

MySQL 쿼리 프로파일 설정

MySQL 쿼리 프로파일

쿼리 프로파일 수집 방법 간단 정리 MyS...

Leave a Comment