내용으로 건너뛰기

Amazon Redshift Serverless에서 쿼리를 실행하지 않는데도 컴퓨트(RPU) 비용이 계속 청구되는 이유와 해결 방법

7분 분량
콘텐츠 수준: 중급
1
  • Redshift에서 워크로드를 바꾸지 않았는데 Amazon Redshift Serverless 비용이 증가했습니다.
  • 컴퓨트 용량(RPU)이 기본 용량으로 내려가지 않고 계속 활성 상태로 유지되며, 쿼리를 실행하지 않는 유휴 시간대에도 과금이 발생합니다.
  • SYS_QUERY_HISTORY를 봐도 이 지속적인 컴퓨트를 설명할 만한 쿼리가 확인되지 않습니다.

원인 요약

Redshift Serverless는 RPU가 활성화 되어 있는 동안 초 단위로 과금하며(최소 60초), 쿼리 부하가 사라져도 즉시 컴퓨트 용량을 기본 수준으로 줄이지 않을 수 있습니다.

공식 문서에 따르면 쿼리 또는 트랜잭션은 완료, 롤백 또는 중지된 이후에야 측정되고 기록되며, 열린 트랜잭션을 종료하거나 롤백하지 않으면 Redshift Serverless는 계속 RPU를 사용하는 것으로 안내되어 있습니다.

즉, 커밋되지 않은 채 열려 있는 트랜잭션이나 닫히지 않은 커서가 있으면, 그 사이 아무 쿼리가 실행되지 않아도 컴퓨트가 유지되어 비용이 발생합니다.

대표적인 두 가지 원인은 다음과 같습니다.

첫째, 애플리케이션이 BEGIN 이후 COMMIT/ROLLBACK을 누락했거나, 큰 결과 집합을 커서로 읽는 도중(예: JDBC/ODBC 드라이버의 autocommit 비활성화 + 작은 fetch size) Fetch 사이에 트랜잭션을 오래 열어 두는 경우입니다.

둘째, 커넥션 풀이 연결 상태 확인을 위해 주기적으로 보내는 경량/빈 쿼리(예: SELECT 1)도 모두 과금 대상 활동으로 처리되어, 실제 워크로드가 없어도 비용이 발생할 수 있습니다.


검증(재현) 결과

17시 40분경 base 8 RPU 워크그룹에서 트랜잭션을 열고(BEGIN) 커서를 선언한 뒤 50행만 Fetch하고 커밋하지 않은 채 두었습니다.

17시 43분 이후 어떤 사용자 쿼리도 실행하지 않았지만, SYS_SERVERLESS_USAGE의 charged_seconds가 매 1분 480초(= 8 RPU × 60초)씩 계속 청구되었습니다.

A. sys_serverless_usage를 통해 확인한 실제 사용량

SELECT start_time, end_time, compute_seconds, compute_capacity, charged_seconds
FROM sys_serverless_usage
ORDER BY end_time DESC;

참고 : https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/SYS_SERVERLESS_USAGE.html

start_timeend_timecompute_capacitycompute_secondscharged_seconds비고
5:40 pm5:41 pm82480데이터 적재 시작
5:41 pm5:42 pm827480BEGIN
5:42 pm5:43 pm8481480Declare CURSOR + Fetch 50
5:43 pm5:44 pm8481480이후 사용자 쿼리 없음. 트랜잭션만 열린 상태
5:44 pm5:45 pm8481480유휴 상태이지만 비용 청구 중
5:45 pm5:46 pm8481480유휴 상태이지만 비용 청구 중
5:46 pm5:47 pm8481480유휴 상태이지만 비용 청구 중
5:47 pm5:48 pm8481480유휴 상태이지만 비용 청구 중

같은 시점에 SVV_TRANSACTIONS에는 17:43:28에 시작된 트랜잭션이 락을 유지하고 있었으나, 실행 중인 사용자 쿼리는 없었습니다.

B. svv_transactions를 통해 확인한 현재 트랜잭션에 대한 정보

SELECT txn_owner, txn_db, xid, pid, txn_start, lockable_object_type, lock_mode
FROM svv_transactions
ORDER BY txn_start;

참고: https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/r_SVV_TRANSACTIONS.html

txn_ownertxn_dbxidpidtxn_startlockable_object_typelock_mode
app_userdev264910738402825:43 pmtransactionidExclusiveLock
app_userdev264910738402825:43 pmrelationAccessShareLock

SYS_QUERY_HISTORY를 보면 마지막 사용자 구문인 FETCH가 17:43:28에 완료된 뒤로는 더 이상 실행된 쿼리가 없습니다. 그럼에도 위 표 A처럼 과금은 계속되었습니다.

C. sys_query_history를 통해 확인한 사용자 쿼리의 세부 정보

SELECT query_id, left(query_text,60) AS qtext, status, start_time
FROM sys_query_history
WHERE start_time > dateadd(minute,-20,getdate())
ORDER BY start_time DESC;

참고: https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/SYS_QUERY_HISTORY.html

query_idqtextstatusstart_time
3243BEGINsuccess5:42 pm
3256DECLARE cur CURSOR FOR SELECT * FROM public.bigsuccess5:43 pm
3260FETCH 50 FROM cursuccess5:43 pm

D. 트랜잭션 종료 이후 상황

열려있던 트랜잭션을 닫았을 때 실제 Compute와 비용이 어떻게 되는지도 함께 확인했습니다. 아래와 같이 롤백(또는 커밋)을 통해 트랜잭션을 종료합니다.

둘 중 무엇을 쓰든 열린 트랜잭션이 닫히면서 커서가 잡고 있던 Compute 점유가 풀리게 됩니다.

ROLLBACK;  -- 또는 COMMIT;

종료 직후부터 사용량을 다시 확인한 결과는 다음과 같습니다.

start_timeend_timecompute_capacitycompute_secondscharged_seconds비고
5:48 pm5:49 pm8481480유지 중 - 청구
5:49 pm5:50 pm8183248ROLLBACK 직후 (17:49:22) - 부분 청구
5:50 pm5:51 pm81480트랜잭션은 닫혔으나 워크그룹 Warm 유지 - 청구
5:51 pm5:52 pm81480Warm 유지 - 청구
5:52 pm5:53 pm81480Warm 유지 - 청구
5:53 pm5:54 pm81480Warm 유지 - 청구
5:54 pm5:55 pm81480Warm 유지 - 청구
5:55 pm5:56 pm81480Warm 유지 - 청구
..................
6:04 pm6:05 pm81480Warm 유지 - 청구
6:05 pm6:06 pm8370워크그룹 auto-suspend - 청구 0

ROLLBACK으로 트랜잭션을 닫는 순간 실제 컴퓨트 작업은 곧바로 멈춥니다.

위 표에서 compute_seconds가 481에서 1로 떨어지는 것이 그 신호이며, 더 이상 일을 하지 않는 상태입니다.

다만 Redshift Serverless 워크그룹은 트랜잭션이 닫혔다고 해서 즉시 꺼지지 않고, 잠시 warm 상태로 남아 base 8 RPU를 계속 청구합니다.

이번 결과에서는 약 15분간(17:50~18:05) charged_seconds가 480으로 유지되다가, 17:56에 워크그룹이 auto-suspend되면서 비로소 0으로 떨어졌습니다.

부하가 사라진 뒤에도 RPU가 일정 시간 유지될 수 있다는 점은 공식 빌링 문서에도 안내되어 있으며, warm 상태로 유지되는 시간은 상황에 따라 달라질 수 있습니다. (일반적으로 15분 이내에 종료됩니다.)

여기서 핵심은, 트랜잭션을 닫아야 워크그룹이 유휴 상태로 들어가 결국 비용이 0으로 떨어진다는 점입니다.

반대로 트랜잭션을 열어 둔 채로 두면 앞의 표 A처럼 charged_seconds가 480으로 계속 유지되어, 이 0으로의 전환 자체가 일어나지 않습니다.


진단 방법

1단계 - Compute Capacity가 유휴 상태에도 유지되는지 확인합니다.

CloudWatch의 ComputeCapacity/ChargedSeconds 또는 Redshift Serverless 콘솔의 컴퓨트 사용량 그래프에서 유휴 구간에 RPU가 기본 용량으로 내려가는지 봅니다.

누적 사용량은 SYS_SERVERLESS_USAGE로 확인 가능합니다.

SELECT start_time, end_time, compute_seconds, compute_capacity, charged_seconds
FROM sys_serverless_usage
ORDER BY end_time DESC;

2단계 - 완료된 쿼리를 확인합니다.

SYS_QUERY_HISTORY 테이블을 통해 Serverless에서 수행된 사용자 쿼리를 확인하실 수 있습니다.

해당 테이블에서 사용량을 정당화할 사용자 쿼리가 거의 없다면, 원인은 정상 워크로드가 아니라 열린 트랜잭션, 닫히지 않은 커서, 또는 커넥션 풀의 keep-alive 트래픽일 가능성이 높습니다.

3단계 - 열린 트랜잭션을 식별합니다.

SVV_TRANSACTIONS 테이블을 통해 트랜잭션에 대한 정보를 확인 가능하며, 이를 통해 오래 열려 있는 트랜잭션을 식별하고 종료합니다.

SELECT txn_owner, txn_db, xid, pid, txn_start, lockable_object_type, lock_mode
FROM svv_transactions
ORDER BY txn_start;

4단계 - 커서/Fetch 활동을 확인합니다.

SYS_CHILD_QUERY_TEXT을 통해 하위 쿼리의 SQL 텍스트를 확인할 수 있습니다.

JDBC/ODBC 드라이버가 커서로 결과를 읽는 경우, 개별 FETCH는 완료된 사용자 쿼리로 잘 드러나지 않고 SYS_CHILD_QUERY_TEXT에 child query로 나타날 수 있습니다.

SELECT user_id, query_id, child_query_sequence, sequence, text
FROM sys_child_query_text
WHERE text ILIKE '%fetch%' OR text ILIKE '%cursor%'
ORDER BY query_id DESC;

참고: https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/SYS_CHILD_QUERY_TEXT.html

5단계 - 커넥션 풀의 keep-alive/validation 쿼리를 점검합니다.

짧은 주기로 도는 SELECT 1 같은 검증 쿼리가 유휴 워크그룹에 과금을 유발하는지 확인합니다.


해결 및 모범 사례

  1. 가장 먼저 보실 부분은 트랜잭션이 제대로 닫히고 있는지입니다.
  • BEGIN으로 트랜잭션을 시작하셨다면 반드시 COMMIT이나 ROLLBACK으로 마무리해 주시고, 정상 경로뿐 아니라 중간에 오류가 났을 때도 트랜잭션이 닫히도록 예외 처리 코드를 함께 점검해 보시면 좋습니다.
  • 트랜잭션이 열린 채로 남아 있는 동안에는 쿼리가 돌지 않아도 컴퓨트가 계속 유지되기 때문입니다.

  1. 커서로 큰 결과를 읽으실 때는 커서를 오래 들고 있지 않는 것이 핵심입니다.
  • 다 읽으셨으면 커서를 바로 닫아 주시고, FETCH와 FETCH 사이에 오래 멈춰 있지 않도록 해 주세요.
  • Fetch size를 너무 작게 잡으면 결과를 끝까지 읽는 내내 트랜잭션이 길게 열려 있게 되니, 이 값도 한번 들여다보시길 권합니다.

  1. 이런 상황이 반복된다면 SESSION TIMEOUT을 걸어 두는 방법도 있습니다.
  • CREATE USER나 ALTER USER에서 이 값을 설정해 두면 유휴 세션이나 비활성 상태로 열려 있는 트랜잭션이 알아서 정리됩니다.
  • 따로 바꾸지 않으면 유휴 세션은 1시간, 열린 채 멈춰 있는 트랜잭션은 6시간 뒤에 종료됩니다.

  1. 커넥션 풀을 쓰고 계시다면 헬스체크 설정도 같이 살펴보시길 권합니다.
  • 연결 상태를 확인하느라 주기적으로 도는 validation/heartbeat 쿼리의 간격을 늘리거나, 꼭 필요하지 않다면 꺼 두시고, 가능하면 TCP keep-alive로 대신하시는 편이 비용 면에서 낫습니다.

참고 문서

AWS
지원 엔지니어

게시됨 한 달 전74회 조회