개발 꿀팁/PHP

PHP에서 MySQL server has gone away 문제

Jammie 2022. 6. 30. 14:49
반응형

1.배경
이전에 Codeigniter에 console 명령 줄과 유사한 스크립트를 썼습니다. 스크립트에 sleep 문장이 존재한 지 오래되었습니다. sleep 이전의 SQL은 모두 성공적으로 작동했지만 sleep 후에 SQL 작업을 다시 실행한 후 오류를 보고했습니다: MySQL server has gone away. 즉 mySQL의 이 연결이 끊겼습니다. 나중에 분석해보니 MySQL에는 두 가지 중요한 구성 매개 변수가 있었습니다.

1.interactive_timeout
2.wait_timeout
두 변수의 단위는 초( s)입니다. 기본값은 8시간(28800)입니다. interactive_ timeout은 단어에서 인터랙션이 일시 정지된 것을 의미합니다. mysql의 연결 방식은 보통 두 가지다. 하나는 '상호작용'이고 다른 하나는 '비상호작용'이다. 일반적으로 mysql-uroot을 사용합니다xxx예를 들어, 자바의 JDBC나 PHP와 같은 PDO를 사용하여 연결을 구동하는 방식은 일반적으로 "비인터랙티브 연결"입니다. 그러나 interactive_timeout은 수정되지 않은 상태에서는 이 값은 변하지 않지만 wait_timeout은 다른 연결 방식에 따라 값이 다릅니다.
wait_timeout의 값은 "대화 연결"에서 interactive_timeout의 값이다. 만약 "비대화 연결"의 경우 wait_timeout의 값은 원래 mysql.cnf에서 구성된 원래 값이다.

wait_timeout 값만 작동합니다. 이 구성 항목은 sleep 상태( show processlist를 통해 현재 연결 수를 볼 수 있는 경우)의 연결을 제한합니다. 만약 이 연결의 슬립 시간이 wait_timeout 값을 초과하면 연결이 끊기거나 지워집니다.

2.wait_timeout 분석
1.mysql.conf 구성 보기

먼저 interactive_timeout=10 wait_timeout=5를 구성했습니다. 이 두 구성 항목의 값은 mysql 클라이언트를 통해 확인할 수 있습니다. show variables like '%timeout%';

2.인터랙티브 연결

클라이언트의 결과: wait_timeout은 우리 msyql.conf의 10s가 아니라 5s였다.

그럼 PHP가 MySQL(비인터랙티브 연결)을 연결하고, 같은 문장을 실행해서 어떤 구조를 얻을 수 있는지 한번 볼까요?

3.비대화 접속

이때 wait_timeout은 원래 mysql.cnf에서 설정한 값이다.

요약하자면: wait_timeout 이 값은 서로 다른 "연결 모드" 아래에 있습니다.도착값이 다릅니다.

3.gone away 원인 분석
위의 상황을 종합하면 우리는 바로 알 수 있다. 처음에는 일부 SQL이 성공적으로 실행되었지만, 나중에는SQL 실행 실패가 gone away를 잘못 보고한 이유는 대부분 wait_timeo를 초과하여 연결이 유휴 상태이기 때문입니다.ut,mysql 서버가 일방적으로 셧다운이 연결. 그러나 클라이언트 코드는 여전히 이 연결 변수를 사용하고 있습니다. 연결은 ok인 줄 알고 있습니다. (사실 mysql server 단자는 연결이 끊겼습니다. 이 연결은 아직 유효하다고 생각함) SQL 실행 오류는 필연적으로 보고됩니다.

그렇다면 우리는 이 상황을 어떻게 해결할 것인가?

1.wait_timeout 값을 적절히 조정하여 크게 하면 쉽게 트리거되지 않습니다.이 gone away의 경우. 하지만 sleep의 긴 연결이 정리되지 않아 자원이 낭비되는 단점이 있다.

2.try-cach를 통해 gone w를 던지면

$db = db();

try {
      fun1$db); // 첫 번째 실행 성공
      sleep(3600*10)  // 가정하다sleep10시간 걸렸어요.
      fun2($db);     // 10시간 뒤에 연결이 되니까mysql처치하여 오보를 초래하다 gone away
}catch(Exception $e) {
   // 오류를 보고한 후에 우리는 무효 접속을 했다close  있다 open새 연결
   $db->close();
   $db->open();
   // 새 연결 실행 받기
   // fun2($db)   
}

3. swoole이나 easyswoole과 같은 프레임을 사용하는 경우 mysql pool을 사용하는 것이 좋습니다. 또한 일반적인 연결 풀은 심박수 검사 ping, 연결 생존 검출 간격 설정, 최대 유휴 연결 수 등의 설정이 있으므로 한 번만 설정하면 됩니다. 예를 들어, msyql 서버에 의해 연결이 종료되지 않도록 활성 연결 간격을 짧게 설정할 수 있습니다. 예를 들어, easyswoole 설정:

예를 들어, 이전에 wait_timeout=10을 설정했는데, 이 easyswoole의 mysql 연결 풀의 활성 간격이 작아지면 gone way가 발생합니다. 첫 번째 인터페이스는 SQL 실행 결과를 반환하는데 성공했지만, 10s가 넘으면 다시 인터페이스에 접속하여 오류를 보고합니다.setIntervalCheckTime() 을(를) 수정하면 이 문제가 발생하지 않습니다. mysql의 show processlist를 통해 접속 수를 확인합니다.

이것들은 모두 이지스울이 우리를 도와준 접속수입니다. sleep이 3초를 넘었을 때, 검사시간이 3초 생존하기 때문에, 연결풀은 우리가 검사를 활성화

반응형