{"id":"IL-0447","org":"every","date":"2024-06-24","docs":[],"title":{"en":"An every RDS for MySQL instance slowed badly when its gp2 EBS BurstBalance ran out and IOPS fell to the baseline","ko":"RDS MySQL 인스턴스의 EBS BurstBalance 가 바닥나 IOPS 가 기준 성능으로 묶이고 데이터베이스 성능이 크게 떨어졌다"},"domain":["database","aws"],"impact":{"scope":"Performance of one RDS for MySQL database dropped sharply","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"A complex query can have a large effect on I/O, so database design and queries need continuous improvement, and query performance needs regular monitoring.","ko":"RDS 에서 BurstBalance 가 바닥나면 예상하지 못한 성능 저하가 올 수 있다. 복잡한 쿼리는 I/O 에 큰 영향을 주므로, 데이터베이스 설계와 쿼리 최적화를 계속 고쳐 나가고 성능을 정기적으로 감시해야 한다."},"related":[],"sources":[{"url":"https://tech.every.tv/entry/2024/06/24/195434","kind":"blog","archived":"https://web.archive.org/web/20260314223918/https://tech.every.tv/entry/2024/06/24/195434"}],"summary":{"en":"The BurstBalance drain came mainly from higher WriteIOPS, and the team found a query that used a lot of I/O. It was a complex SELECT whose I/O jumped while it ran; its execution plan showed Using temporary, Using filesort in Extra, meaning an internal sort and writes to a temporary table. The team concluded that these temporary table writes used up the BurstBalance, after which the 30GiB gp2 volume was limited to its 100 IOPS baseline.\n\nWhy the query suddenly began writing so much to temporary tables was still under investigation when the article was written. One possibility the team gives is that the temporary tables grew with the accumulating data until they passed the limit for in-memory processing and spilled to disk. The article lists possible countermeasures: tuning the query by reviewing indexes or rewriting it, moving from gp2 to gp3 or enlarging the storage, adjusting tmp_table_size and max_heap_table_size, a larger instance type, and monitoring BurstBalance with CloudWatch alerts and the service with external monitoring such as Pingdom.","ko":"every 의 한 RDS 인스턴스는 MySQL 5.7.44, db.t3.medium, 범용 SSD gp2 30GiB 였다. 이 인스턴스에서 BurstBalance 가 갑자기 빠르게 줄어 바닥났고, 데이터베이스 성능이 크게 떨어졌다. gp2 볼륨의 기준 성능은 3 IOPS/GB 이고 최소 100 IOPS 다. gp2 볼륨은 IOPS 가 기준 성능을 넘으면 크레딧을 써서 최대 3,000 IOPS 까지 내고, 크레딧이 바닥나면 기준 성능으로 묶인다. 30GiB 볼륨의 기준 성능은 100 IOPS 다.\n\n조사해 보니 BurstBalance 는 주로 WriteIOPS 가 늘어서 줄었다. 복잡한 SELECT 문의 실행 계획에 Using temporary, Using filesort 가 있었고, 팀은 이 쿼리가 임시 테이블에 대량으로 쓰면서 BurstBalance 를 빠르게 썼다고 봤다. 이 쿼리가 어느 시점부터 갑자기 임시 테이블에 많이 쓰게 된 이유는 아직 조사 중이다. 팀은 데이터가 날마다 쌓여 이 쿼리의 임시 테이블이 메모리 안에서 처리할 수 있는 한도를 넘고 디스크에 쓰이기 시작했을 가능성을 짐작하고 있다. 팀이 든 대책은 쿼리 튜닝, gp3 이전이나 스토리지 증설로 기준 IOPS 높이기, tmp_table_size 와 max_heap_table_size 조정, 인스턴스 타입 변경, BurstBalance 감시와 Pingdom 같은 외부 모니터링이었다."},"trigger":{"en":"A complex SELECT query began writing large amounts of data to temporary tables, which raised WriteIOPS and used up the burst credits.","ko":"복잡한 SELECT 문이 어느 시점부터 갑자기 임시 테이블에 대량으로 쓰기 시작해 WriteIOPS 가 늘었다. 그렇게 바뀐 이유는 아직 조사 중이다."},"severity":"unknown","symptoms":["database-overloaded","throughput-degraded"],"timeline":{"detected_after":null,"resolved_after":null},"date_kind":"published","detection":null,"components":["database","block-storage"],"root_cause":"capacity","remediation":[],"action_items":[{"text":{"en":"Consider tuning the query by reviewing indexes and rewriting it","ko":"문제 쿼리를 튜닝하는 것을 검토한다. 인덱스를 다시 보거나, 서브쿼리를 없애고 JOIN 을 최적화하는 식으로 쿼리를 다시 쓰는 방안이다."}},{"text":{"en":"Consider moving the storage from gp2 to gp3 or increasing its size to raise the baseline IOPS","ko":"gp2 볼륨을 성능 특성을 더 예측하기 쉬운 gp3 로 옮기거나, 스토리지를 늘려 기준 IOPS 를 높이는 것을 검토한다."}},{"text":{"en":"Consider adjusting tmp_table_size and max_heap_table_size","ko":"임시 테이블의 크기 한도를 정하는 tmp_table_size 와 max_heap_table_size 파라미터를 조정하는 것을 검토한다."}},{"text":{"en":"Consider moving to a more powerful instance type","ko":"더 성능이 높은 인스턴스 타입으로 옮기는 것을 검토한다."}},{"text":{"en":"Consider monitoring BurstBalance with CloudWatch alerts and adding external monitoring such as Pingdom","ko":"CloudWatch 알림 같은 수단으로 BurstBalance 를 감시하고, Pingdom 같은 외부 모니터링을 두는 것을 검토한다."}}],"contributing":["inefficient-query"],"recurrence_of":null,"symptoms_text":{"en":"The BurstBalance of an RDS instance began to fall rapidly and finally ran out, and the database's performance dropped sharply. The instance ran MySQL 5.7.44 on db.t3.medium with general purpose SSD (gp2) storage of 30GiB.\n\nOn gp2 volumes, BurstBalance is the remaining credit for running above the baseline IOPS. The baseline is 3 IOPS/GB with a minimum of 100 IOPS, bursts go up to 3,000 IOPS, and the maximum credit is 5.4 million I/O credits. When BurstBalance is empty, IOPS is held to the baseline: for this 30GiB volume, 3 IOPS/GB gives 90 IOPS, so the minimum of 100 IOPS applied.\n\nThe team checked the CloudWatch metrics BurstBalance, ReadIOPS and WriteIOPS, the RDS error log and the slow query log, and used Performance Insights to find the queries at fault and read their execution plans. BurstBalance fell as WriteIOPS rose. At an assumed hourly average of 600 WriteIOPS, the balance would be used up in about 3 hours.","ko":"RDS 인스턴스의 BurstBalance 가 갑자기 빠르게 줄기 시작해 끝내 바닥났고, 데이터베이스 성능이 크게 떨어졌다. 인스턴스는 MySQL 5.7.44, db.t3.medium, 범용 SSD gp2 30GiB 였다.\n\nBurstBalance 는 gp2 볼륨이 기준 성능을 넘어 잠시 높은 IOPS 를 낼 수 있게 해 주는 크레딧의 남은 양이다. 바닥나면 IOPS 가 기준 성능으로 묶인다. 30GiB 볼륨의 기준 성능은 3 IOPS/GB 로 계산한 90 IOPS 가 아니라 최소값인 100 IOPS 다.\n\nCloudWatch 에서 BurstBalance 와 WriteIOPS 를 함께 보면 WriteIOPS 가 늘 때 BurstBalance 가 줄었다. 1시간 평균 WriteIOPS 를 600 으로 잡고 계산하면 기준 성능 100 을 넘는 500 IOPS 를 3,600초 동안 쓰므로 1시간에 크레딧이 1,800,000 줄고, 최대 크레딧 5,400,000 이 3시간 만에 바닥난다.\n\n팀은 CloudWatch 지표, RDS 오류 로그, 슬로 쿼리 로그, Performance Insights 를 보고 문제 쿼리의 실행 계획을 분석했다. I/O 를 크게 쓰는 복잡한 SELECT 문이 있었고, 이 쿼리를 실행할 때 I/O 가 치솟았다. 실행 계획의 extra 에는 Using temporary, Using filesort 가 있어 내부 정렬과 임시 테이블 쓰기가 일어나고 있었다."},"updated_at":"2026-11-14T12:34:09.639146Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0447","org_slug":"every"}