MySQL 자체 이외의 다른 요소를 표적으로 삼을 가능성을 어떻게 분석합니까?
저자: ACOS DBA팀의 공탕지에(Gong Tangjie)는 주로 MySQL 기술지원을 담당하고 있으며, MySQL, PG, 국내 데이터베이스에 능숙하다.
Aikeson 오픈 소스 커뮤니티에서 제작된 원본 콘텐츠는 승인 없이 사용할 수 없습니다. 편집자에게 연락하여 재인쇄할 출처를 명시해 주세요.
이 글은 1,200단어 정도이며 읽는 데 3분 정도 소요될 것으로 예상됩니다.
배경
일괄 작업을 실행하는 동안 애플리케이션에 문제가 발생했습니다. 일부 작업에 대한 데이터베이스 연결이 갑자기 끊어져 작업을 완료할 수 없게 되었습니다. 데이터베이스의 오류 로그에서 Aborted 연결 정보가 발견되었는데, 이는 클라이언트와 서버 간의 통신이 비정상적으로 중단되었음을 나타냅니다.
분석하다
문제의 원인을 찾기 위해 먼저 경험을 바탕으로 연결이 중단될 수 있는 몇 가지 일반적인 상황을 분석했습니다.
- 클라이언트가 연결을 제대로 닫지 않았으며
mysql_close()
함수를 호출하지 않았습니다. - 클라이언트의 유휴 시간이
wait_timeout
또는interactive_timeout
매개변수의 초를 초과하면 서버의 연결이 자동으로 끊어집니다. - 클라이언트가 보내거나 받는 패킷의 크기가
max_allowed_packet
해당 매개변수 값을 초과하여 연결이 중단되는 경우가 있습니다. - 클라이언트가 데이터베이스에 액세스하려고 시도했지만 권한이 없었거나, 잘못된 비밀번호가 사용되었거나, 연결 패킷에 올바른 정보가 포함되어 있지 않았습니다.
그러나 조사 결과 위의 상황 중 어느 것도 현재 문제에 적용되지 않는 것으로 나타났습니다. 이전에는 작업이 정상적으로 실행 중이었고 프로그램이 변경되지 않았으므로 첫 번째 상황은 배제할 수 있습니다. MySQL의 시간 초과 매개 변수를 확인한 wait_timeout
결과 interactive_timeout
둘 다 28800으로 8시간으로 작업 실행 시간을 훨씬 초과하므로 두 번째 상황은 배제할 수 있습니다. 또한 클라이언트와 서버의 매개변수를 확인한 max_allowed_packet
결과 둘 다 64M이고 이 제한을 초과할 가능성이 낮으므로 세 번째 상황은 배제할 수 있습니다. 또한 클라이언트의 데이터베이스 접근 권한, 비밀번호, 연결 패키지 및 기타 정보가 모두 올바른지 확인했기 때문에 네 번째 상황은 배제될 수 있습니다.
이 시점에서 우리는 처음에는 MySQL 수준에서는 문제가 없어야 하고 문제는 다른 곳에 있을 수 있다고 생각합니다.
문제를 더 자세히 찾기 위해 다음과 같이 서버의 일부 관련 커널 매개변수를 수정하려고 했습니다.
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_time = 120
net.core.rmem_default = 2097152
net.core.wmem_default = 2097152
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_syn_backlog = 16384
이러한 매개변수는 주로 네트워크 연결의 성능과 안정성을 최적화하고 연결이 예기치 않게 종료되거나 시간 초과되는 것을 방지하기 위한 것입니다. 그러나 수정된 결과는 개선되지 않았으며 여전히 연결이 비정상적으로 중단됩니다.
마지막으로 Wireshark 도구를 사용하여 패킷 캡처 분석을 시도한 결과 서버가 클라이언트에 대량의 ACK 패킷을 보내는 비정상적인 현상을 발견했습니다. 아래 그림과 같이:
이러한 ACK 패킷은 TCP 프로토콜의 확인 패킷으로, 서버가 클라이언트의 데이터 패킷을 수신했으며 클라이언트에 데이터 전송을 계속하도록 요청함을 나타냅니다. 그런데 왜 서버는 그렇게 많은 ACK 패킷을 보내는 걸까요? 네트워크에 이상이 발생하여 클라이언트가 서버에서 반환한 ACK 패킷을 받지 못하는 것으로 추측됩니다. 따라서 서버는 시간이 초과되거나 클라이언트로부터 응답을 받을 때까지 반복적으로 ACK 패킷을 보냅니다. 그러나 네트워크 담당자의 조사 결과 뚜렷한 문제는 발견되지 않았습니다.
패킷 캡처를 계속 분석하면서 우리는 또 다른 비정상적인 현상을 발견했습니다. 클라이언트가 보내는 서버에 몇 가지 창 경고를 표시하는 것입니다. 아래 그림과 같이:
이러한 창 경고는 TCP 프로토콜의 흐름 제어 메커니즘으로, 서버 또는 클라이언트의 수신 창이 가득 차서 더 이상 데이터를 받을 수 없음을 나타냅니다.
[TCP Window Full]은 송신 측에서 수신 측으로 보내는 윈도우 경고로, 데이터 수신 측의 한계에 도달했음을 나타냅니다.
[TCP ZeroWindow]는 수신측에서 송신측으로 보내는 창 경고로, 수신측의 수신 창이 가득 차서 일시적으로 전송을 중지함을 발신자에게 알립니다.
위 정보를 바탕으로 문제의 원인은 다음과 같습니다. MySQL이 전송해야 하는 데이터가 너무 크기 때문에 클라이언트의 TCP 캐시가 가득 차서 클라이언트가 TCP의 데이터를 소화할 때까지 기다려야 합니다. 데이터를 계속 수신하기 전에 캐시합니다. 그러나 이 기간 동안 MySQL은 클라이언트에게 계속해서 데이터를 보내도록 요청합니다. 클라이언트가 일정 시간(기본값은 60초) 내에 응답하지 않으면 MySQL은 데이터 전송 시간이 초과된 것으로 간주하여 연결을 중단합니다.
추측을 검증하기 위해 MySQL의 느린 로그를 확인해 본 결과 Last_errno: 1161 레코드 가 많이 발견되었습니다 .
이러한 기록은 MySQL이 데이터를 보낼 때 시간 초과 오류가 발생했음을 나타내며 발생 횟수는 애플리케이션 실패 작업 수와 매우 가깝습니다. MySQL 공식 웹사이트에 따르면 이 오류의 의미는 다음과 같습니다.
오류 번호: 1161; 기호: ER_NET_WRITE_INTERRUPTED; SQL상태: 08S01
메시지: 통신 패킷 쓰기 시간이 초과되었습니다.
이는 네트워크 쓰기가 중단된다는 의미라고 볼 수 있는데, 이를 제어하는 MySQL 레벨의 파라미터가 있으므로 net_write_timeout 파라미터를 600으로 변경해 주면 배치 작업이 정상적으로 실행될 것이다.
따라서 MySQL 연결이 비정상적으로 중단되는 이유는 클라이언트가 획득한 데이터베이스가 너무 커서 클라이언트의 TCP 캐시를 초과하기 때문입니다. 이 기간 동안 클라이언트는 먼저 캐시에 있는 데이터를 처리해야 합니다. 클라이언트는 계속해서 데이터를 전송하지만 클라이언트가 60초 이내에 응답하지 못하여 MySQL이 데이터 전송 시간을 초과하고 연결을 중단했습니다.
결론적으로
이상의 분석과 시도를 통해 우리는 다음과 같은 결론에 도달했다.
- 패킷 캡처 정보에는 클라이언트의 캐시가 가득 차서 제때에 서버에 피드백을 할 수 없기 때문에 ACK 정보가 많아 서버는 60초(
net_write_timeout
기본값은 60) 이상까지 ACK 정보를 반복해서 보내게 되어 오류가 발생합니다. MySQL은 연결을 중단합니다. - 느린 로그에는 실제로 MySQL에서 SQL을 실행했기 때문에 Last_errno:1161 레코드가 많이 있는데, 클라이언트로 데이터를 보낼 때 그 양이 클라이언트의 TCP 캐시를 초과하여 클라이언트 애플리케이션에서 처리를 하지 못한 경우가 있습니다. 60초 이내에 데이터를 캐시에 저장하므로 클라이언트에 데이터를 보낼 때 MySQL이 시간 초과됩니다.
- MySQL 수준에서 매개변수를 조정하면
net_write_timeout
이 현상이 완화될 수 있습니다. 근본 원인은 단일 SQL로 얻은 데이터의 양이 너무 커서 애플리케이션이 캐시에 있는 데이터를 짧은 시간에 처리할 수 없기 때문입니다. 이로 인해 후속 데이터 전송 시간이 초과됩니다.
최적화 제안
- 단일 SQL 쿼리가 서버에서 대량의 데이터를 가져오는 것을 방지하기 위해 비즈니스 수준에서 데이터를 일괄 처리하므로 클라이언트 측에서 TCP 캐시가 부족해집니다.
- MySQL에서 매개변수를 늘리
net_write_timeout
거나 클라이언트의 TCP 캐시를 늘리면 이러한 상황을 완화할 수 있지만, 너무 많은 데이터가 여전히 성능과 안정성에 영향을 미치기 때문에 문제를 완전히 해결할 수는 없습니다. - LIMIT, WHERE 등의 조건을 사용하거나 집계 함수, 그룹화 함수 등을 사용하는 등 불필요한 데이터 반환을 줄이기 위해 SQL 문을 최적화하여 데이터 양을 줄이고 쿼리 효율성을 향상시킵니다.
더 많은 기술 기사를 보려면 https://opensource.actionsky.com/을 방문하세요.
SQLE 소개
SQLE는 개발부터 프로덕션 환경까지 SQL 감사 및 관리를 포괄하는 포괄적인 SQL 품질 관리 플랫폼입니다. 주류 오픈소스, 상용 및 국내 데이터베이스를 지원하고 개발, 운영 및 유지 관리를 위한 프로세스 자동화 기능을 제공하고 온라인 효율성을 향상시키며 데이터 품질을 향상시킵니다.