Amazon RDS MySQL 인스턴스에서 높은 CPU 사용량을 디버깅하기 위해 고군분투


21

m1.xlarge MySQL RDS 서버를 실행 중이며 CPU 사용률에 문제가 있습니다. 몇 주 전에 큰 인스턴스에서 CPU 사용률이 100 %에 도달하는 데 몇 가지 문제가있었습니다. 크기를 xlarge로 업그레이드하면 잠시 동안 안정되었지만 CPU 사용량이 점차 다시 커졌습니다.

지난 주 정도 동안 CPU 사용률은 90 년대에 계속 높아져 어제 100 % 또는 그 이상으로 지속적으로 도달하여 생산 현장이 중단되었습니다. db 서버를 재부팅 한 후 몇 시간 내에 CPU 사용량이 동일한 수준으로 다시 상승했습니다.

mysql 서버에서 show processlist를 실행했으며 MySQL 관리자를 통해 동일한 것을 모니터링하고 있습니다. 특히 오래 실행되는 쿼리 나 많은 양의 쿼리가없는 것 같습니다. 오랫동안 휴면 상태에있는 몇 가지 프로세스가 있습니다 ...이 데이터베이스와 통신하는 기본 앱 외부에서 실행되는 격리 된 작업자 데몬입니다. 서버 이름이 변경된 프로세스 목록 출력에서 ​​서버 이름이 무엇인지 설명하기 위해 복사했습니다.

+------+----------+---------------------------------------------------+--------------+---------+-------+--------------+----------------------------------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+------+----------+---------------------------------------------------+--------------+---------+-------+--------------+----------------------------------------------------------------------------------------+
| 13 | rdsadmin | localhost:43513 | mysql | Sleep | 14 | | NULL |
| 15 | proddbuser | app-server-1.eu-west-1.compute.internal:36460 | proddb | Sleep | 46 | | NULL |
| 451 | proddbuser | app-server-1.eu-west-1.compute.internal:55512 | proddb | Sleep | 29 | | NULL |
| 912 | proddbuser | app-server-1.eu-west-1.compute.internal:45171 | proddb | Sleep | 13 | | NULL |
| 941 | proddbuser | app-server-1.eu-west-1.compute.internal:47353 | proddb | Sleep | 53 | | NULL |
| 951 | proddbuser | app-server-1.eu-west-1.compute.internal:48014 | proddb | Sleep | 37 | | NULL |
| 1009 | proddbuser | app-server-1.eu-west-1.compute.internal:51787 | proddb | Sleep | 36 | | NULL |
| 1041 | proddbuser | app-server-1.eu-west-1.compute.internal:53777 | proddb | Sleep | 14 | | NULL |
| 1572 | proddbuser | app-server-1.eu-west-1.compute.internal:42989 | proddb | Sleep | 3 | | NULL |
| 1592 | proddbuser | app-server-1.eu-west-1.compute.internal:43279 | proddb | Sleep | 162 | | NULL |
| 2909 | proddbuser | app-server-1.eu-west-1.compute.internal:37768 | proddb | Sleep | 35 | | NULL |
| 3028 | proddbuser | app-server-1.eu-west-1.compute.internal:42568 | proddb | Sleep | 5 | | NULL |
| 3119 | proddbuser | app-server-1.eu-west-1.compute.internal:46913 | proddb | Sleep | 76 | | NULL |
| 3189 | proddbuser | app-server-1.eu-west-1.compute.internal:51466 | proddb | Sleep | 5 | | NULL |
| 3216 | proddbuser | app-server-2.eu-west-1.compute.internal:44097 | proddb | Sleep | 14552 | | NULL |
| 3218 | proddbuser | app-server-2.eu-west-1.compute.internal:44099 | proddb | Sleep | 14552 | | NULL |
| 3219 | proddbuser | app-server-2.eu-west-1.compute.internal:44107 | proddb | Sleep | 44 | | NULL |
| 3220 | proddbuser | app-server-2.eu-west-1.compute.internal:44113 | proddb | Sleep | 26 | | NULL |
| 3223 | proddbuser | app-server-2.eu-west-1.compute.internal:44184 | proddb | Sleep | 50 | | NULL |
| 3224 | proddbuser | app-server-2.eu-west-1.compute.internal:44187 | proddb | Sleep | 1 | | NULL |
| 3226 | proddbuser | app-server-2.eu-west-1.compute.internal:44208 | proddb | Sleep | 33 | | NULL |
| 3229 | proddbuser | app-server-2.eu-west-1.compute.internal:44250 | proddb | Sleep | 14 | | NULL |
| 3232 | proddbuser | app-server-2.eu-west-1.compute.internal:44279 | proddb | Sleep | 26 | | NULL |
| 3233 | proddbuser | app-server-2.eu-west-1.compute.internal:44297 | proddb | Sleep | 31 | | NULL |
| 3237 | proddbuser | app-server-2.eu-west-1.compute.internal:44334 | proddb | Sleep | 27 | | NULL |
| 3239 | proddbuser | app-server-2.eu-west-1.compute.internal:44338 | proddb | Sleep | 11 | | NULL |
| 3241 | proddbuser | app-server-2.eu-west-1.compute.internal:44356 | proddb | Sleep | 26 | | NULL |
| 3260 | proddbuser | app-server-2.eu-west-1.compute.internal:44619 | proddb | Sleep | 8 | | NULL |
| 3337 | proddbuser | utility-server-1.eu-west-1.compute.internal:45193 | proddb | Query | 0 | Sending data | SELECT `mytable`.* FROM `mytable` WHERE `mytable`.`foreign_key` = 309416 LIMIT 1 |
| 3419 | proddbuser | utility-server-1.eu-west-1.compute.internal:46136 | proddb | Query | 0 | Sending data | SELECT `mytable`.* FROM `mytable` WHERE `mytable`.`foreign_key` = 284530 LIMIT 1 |
| 3463 | proddbuser | app-server-1.eu-west-1.compute.internal:59619 | proddb | Sleep | 9406 | | NULL |
| 3504 | proddbuser | utility-server-1.eu-west-1.compute.internal:47063 | proddb | Query | 0 | Sending data | SELECT `mytable`.* FROM `mytable` WHERE `mytable`.`foreign_key` = 260571 LIMIT 1 |
| 3577 | proddbuser | app-server-1.eu-west-1.compute.internal:34394 | proddb | Sleep | 6734 | | NULL |
| 3585 | proddbuser | utility-server-1.eu-west-1.compute.internal:47990 | proddb | Query | 0 | Sending data | SELECT `mytable`.* FROM `mytable` WHERE `mytable`.`foreign_key` = 231273 LIMIT 1 |
| 3664 | proddbuser | utility-server-1.eu-west-1.compute.internal:48909 | proddb | Query | 0 | Sending data | SELECT `mytable`.* FROM `mytable` WHERE `mytable`.`foreign_key` = 201525 LIMIT 1 |
| 3716 | proddbuser | app-server-2.eu-west-1.compute.internal:56301 | proddb | Sleep | 27 | | NULL |
| 3748 | proddbuser | utility-server-1.eu-west-1.compute.internal:49850 | proddb | Query | 0 | Sending data | SELECT `mytable`.* FROM `mytable` WHERE `mytable`.`foreign_key` = 167839 LIMIT 1 |
| 3771 | proddbuser | my-pc:30101 | NULL | Query | 0 | NULL | show processlist |
| 3831 | proddbuser | utility-server-1.eu-west-1.compute.internal:50785 | proddb | Query | 0 | Sending data | SELECT `mytable`.* FROM `mytable` WHERE `mytable`.`foreign_key` = 123228 LIMIT 1 |
+------+----------+---------------------------------------------------+--------------+---------+-------+--------------+----------------------------------------------------------------------------------------+

또한이 시간대에는 정상 피크 시간에 비해 사이트의 트래픽이 매우 적으며 피크 시간에 볼 수있는 부하의 약 10 %를 말합니다.

또한 가장 시간이 많이 걸리는 앱 데이터베이스 호출이 무엇인지 보여주는 새로운 유물 모니터링 기능도 있습니다. 앱이 db에서 소비하는 시간의 99 %를 차지하는 특정 호출은 다음과 같이 id 쿼리로 간단히 찾는 것입니다.

SELECT `mytable`.* FROM `mytable` WHERE `mytable`.`id` = 123 LIMIT 1

(위의 프로세스 목록에서 실행중인 쿼리와는 동일하지 않음)

이 작업은 지난 주 정도에 걸쳐 시간 요청 사이의 표준 편차가 증가하고 최대 시간 (초)으로 측정되는 속도가 느려졌습니다. 나는 이것이 원인이 아닌 CPU 사용률 문제의 결과라고 생각합니다.

이 테이블에는 약 80,000 개의 행이 있으므로 크지 않습니다. 데이터베이스의 대부분의 앱 시간은이 테이블에서 레코드를 조회하는 데 소요되며 앱의 주요 기능은이 기능을 기반으로합니다. CPU 사용량이 약 100 %이며 1 또는 2 ms 이내에 응답하는 동안 내 앱 서버에서 프로덕션 데이터베이스로 비슷한 쿼리를 직접 실행했습니다.

위의 모든 내용을 바탕으로 디버깅을 진행하는 방법을 잘 모릅니다. 근본 원인이 될 수있는 아이디어가 무엇인지, 어떻게 조사해야하는지 궁금한 사람이 있습니까? db 서버를 실행하는 기본 서버에 대한 액세스는 Amazon RDS 인스턴스 이후로 제한됩니다.


방금 RDS를 다시 시작하여 문제가 해결되었습니다
shareef

답변:


14

이 문제를 해결하기 위해 관리 한 단계는 다음과 같습니다.

먼저 토론 포럼에 게시하여 Amazon RDS 팀에 연락하여이 CPU를 모두 사용하는 mysqld 프로세스임을 확인했습니다. 이렇게하면 물리적 서버에서 실행중인 다른 구성 오류가 사라졌습니다.

두 번째로 실행중인 쿼리 소스를 추적했습니다.

SELECT `mytable`.* FROM `mytable` WHERE `mytable`.`foreign_key` = 231273 LIMIT 1 

show processlist 출력을 모니터링 할 때 이러한 쿼리 중 특히 오래 걸리지 않았기 때문에 원래 원인으로 이것을 간과했습니다. 다른 길을 다 쓴 후에, 나는 그것이 후속 할 가치가 있다고 결정했다.…

show processlist 출력에서 ​​볼 수 있듯이 이러한 쿼리는 주요 응용 프로그램 코드 외부에 존재하는 일부 전술 유틸리티 작업을 실행하는 utlility 서버에서 온 것입니다. 이것이 새로운 유물 에이전트가 기본 앱 서버에만 설치되기 때문에 새로운 유물 모니터링에서 느리게 표시되거나 문제를 일으키지 않는 이유입니다.

이 안내서를 느슨하게 따라 가기 :

http://www.mysqlperformanceblog.com/2007/02/08/debugging-sleeping-connections-with-mysql/

유틸리티 서버 상자에서 특정 실행 프로세스로 이러한 쿼리를 추적 할 수있었습니다. 이것은 약 70,000 개의 레코드를 매우 비효율적으로 반복하고 일부 필드 값을 확인하고 그 값을 사용하여 'mytable'에서 새 레코드를 작성해야하는지 여부를 결정하는 루비 코드입니다. 내가 결정할 수있는 분석을 한 후에는 더 이상 프로세스가 필요하지 않아 죽일 수있었습니다.

문제를 악화시키는 것은 cron 작업이 구성되는 방식과 각 프로세스에 걸린 시간으로 인해 같은 프로세스의 인스턴스가 한 번에 6 개씩 실행되는 것 같습니다! 이러한 프로세스를 중단 시켰고 CPU 사용량이 약 100 %에서 약 5 %로 떨어졌습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.