오류 2006 : MySQL 서버가 사라졌습니다


8

uWSGI와 nginx를 사용하여 CentOS 서버에서 Python Pyramid 앱을 실행하고 있습니다. SQLAlchemy를 ORM으로, MySQLdb를 API로, MySQL을 데이터베이스로 사용하고 있습니다. 이 사이트는 아직 운영되지 않았으므로 유일한 트래픽은 나와 다른 회사 직원입니다. 데이터베이스를 채우기 위해 일부 데이터를 구입 했으므로 가장 크고 가장 자주 쿼리되는 테이블은 ~ 150,000 행입니다.

어제 웹 사이트의 새 탭 4 개를 빠르게 연속으로 열었고 502 개의 잘못된 게이트웨이 오류가 발생했습니다. uWSGI 로그를보고 다음을 발견했습니다.

sqlalchemy.exc.OperationalError: (OperationalError) (2006, 'MySQL server has gone away') 'SELECT ge...

중요 사항 : 이 오류는 MySQL의 wait_timeout으로 인한 것이 아닙니다. 거기에 있었어요.

동시 요청이 동시에 제공되어 문제가 발생했는지 궁금합니다. 나는 나 자신을 가난한 사람의 부하 시험기로 만들었다.

for i in {1..10}; do (curl -o /dev/null http://domain.com &); done;

물론, 그 10 건의 요청에서 적어도 한 번은 2006 년 오류가 발생하는 경우가 많습니다. 때로는 오류가 생소 할 수도 있습니다. 예를 들면 다음과 같습니다.

sqlalchemy.exc.NoSuchColumnError: "Could not locate column in row for column 'table.id'"

열이 가장 확실하게 존재하고 다른 모든 동일한 요청에서 제대로 작동했을 때. 또는이 하나 :

sqlalchemy.exc.ResourceClosedError: This result object does not return rows. It has been closed automatically.

다시 한 번 다른 모든 요청에 ​​제대로 작동했을 때.

문제가 동시 데이터베이스 연결에서 비롯된 것임을 추가로 확인하기 위해 uWSGI를 단일 작업자로 설정하고 멀티 스레딩을 비활성화하여 요청을 한 번에 하나씩 처리하도록했습니다. 물론 문제는 사라졌습니다.

문제를 찾기 위해 MySQL에 대한 오류 로그를 설정했습니다. MySQL 시작 중 일부 알림을 제외하고는 비어 있습니다.

내 MySQL 설정은 다음과 같습니다.

[mysqld]
default-storage-engine = myisam
key_buffer = 1M
query_cache_size = 1M
query_cache_limit = 128k
max_connections=25
thread_cache=1
skip-innodb
query_cache_min_res_unit=0
tmp_table_size = 1M
max_heap_table_size = 1M
table_cache=256
concurrent_insert=2
max_allowed_packet = 1M
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 64K
innodb_file_per_table=1
log-error=/var/log/mysql/error.log

오류에 대한 무거운 인터넷 검색은 거의 공개하지 않았지만 max_allowed_packet을 늘릴 것을 제안했습니다. 100M으로 늘리고 MySQL을 다시 시작했지만 전혀 도움이되지 않았습니다.

요약 : MySQL에 대한 동시 연결로 인해 2006, 'MySQL server has gone away'다른 이상한 오류가 발생합니다. MySQL의 오류 로그에는 아무런 관련이 없습니다.

나는 몇 시간 동안이 일을하고 있으며 아무런 진전이 없었습니다. 누군가 나를 도울 수 있습니까?


동시 요청을 처리 할 때 각 스레드 (또는 프로세스 또는 기타)가 데이터베이스에 자체적으로 연결되어 있습니까?
DerfK

각 프로세스에는 SQLAlchemy가 관리하는 연결 풀이 있으므로 각 요청에는 고유 한 연결이 있어야합니다.
Theron Luhn

또 다른 참고 사항 :로드 테스트는 로컬 개발 서버 (서버의 웨이트리스 및 데이터베이스의 MySQL)에서 아무런 문제를 일으키지 않습니다.
Theron Luhn

답변:


18

나는 이것도 만났고 그 이유와 해결책을 찾았다.

이것이 발생하는 이유는 응용 프로그램이 부모에로드 된 후 python uwsgi 플러그인 (또는 모든 uwsgi 플러그인)이 새로운 작업자를 fork ()하기 때문입니다. 결과적으로 자식은 부모로부터 모든 리소스 (db 연결과 같은 파일 디스크립터 포함)를 상속받습니다.

uwsgi wiki 에서 이에 대해 간단히 읽을 수 있습니다 .

uWSGI는 가능할 때마다 쓰기시 fork () 사본을 남용하려고합니다. 기본적으로 응용 프로그램을로드 한 후 포크됩니다. 해당 동작을 원하지 않으면 --lazy 옵션을 사용하십시오. 그것을 활성화하면 uWSGI가 각 작업자의 포크 () 후에 응용 프로그램을로드하도록 지시합니다.

아시다시피, 파이썬의 mysqldb 연결과 커서는 명시 적으로 보호하지 않으면 스레드로부터 안전하지 않습니다. 따라서 동일한 mysql 연결 / 커서를 동시에 사용하는 여러 프로세스 (예 : uwsgi worker)가이를 손상시킵니다.

내 경우 ( King Arthur의 Gold API의 경우) 다른 모듈 범위에서 요청 당 MySQL 연결을 만들 때 제대로 작동했지만 성능을 돕기 위해 지속적인 연결을 원할 때 데이터베이스 연결과 커서를 전역 범위로 옮겼습니다. 부모 모듈. 결과적으로, 나의 연결은 당신처럼 서로 밟고있었습니다.

이에 대한 해결책은 "lazy"키워드 (또는 --lazy 명령 행 옵션)를 uwsgi 구성에 추가하는 것입니다. 결과적으로 응용 프로그램은 부모로부터 분기하고 연결을 공유하는 대신 각 자식마다 새로 분기됩니다 (그리고 어느 시점에서 스테핑하면 MySQL 서버가 손상된 요청으로 인해 강제로 닫힙니다).

마지막으로, uwsgi 구성을 수정하지 않고이 방법을 원한다면 작업자 프로세스가 실행 된 직후 @postfork 데코레이터를 사용하여 새 데이터베이스 연결을 올바르게 만들 수 있습니다. 여기에서 그것에 대해 읽을 수 있습니다 .

후속 조치에서 이미 pgsql로 전환 한 것으로 보았지만 여기에 답이있어 밤에 더 잘 수 있고 당신과 같은 사람과 나는 이것에 대한 답을 찾으려고 노력합니다!

추신 : 문제에 대한 이해가 있었지만 (작업자가 서로 밟아 커서가 손상됨) fork () 및 --lazy에 대해 조금도 알지 못했지만 작업자가 " 전역 범위의 풀에서 mysql 연결을 체크 아웃 한 다음 application ()을 종료하기 직전에 "체크 인"하지만 웹 / 응용 프로그램로드가 지속적으로 변할 정도로 충분히 변하지 않는 한 --lazy를 사용하는 것이 훨씬 좋습니다 새로운 노동자 만들기. 그럼에도 불구하고 나는 자신의 db 연결 풀을 구현하는 것보다 훨씬 깨끗하기 때문에 --lazy를 선호 할 수 있습니다.

편집 : 여기 에이 문제에 직면 한 다른 사람들을 위해 정보가 부족하기 때문에이 문제 + 솔루션에 대한 자세한 내용은 다음과 같습니다. http://tns.u13.net/?p=190


무엇이 원인인지 아는 것이 좋습니다. 감사합니다!
Theron Luhn

이 게시물이 내가 가지고있는 것과 똑같은 문제 였고 솔루션에서 해결했습니다 :) 감사합니다!
MasterGberry

"따라서 동일한 mysql 연결 / 커서를 동시에 사용하는 여러 프로세스 (uwsgi 워커와 같은)는이를 손상시킵니다." 이것은 매우 유익했습니다. 로컬에서 동일한 데이터베이스에 두 개의 연결이 열려 있고 (하나는 셸에서, 다른 하나는 wsgi 응용 프로그램에서)이 오류가 발생했습니다. 데이터베이스가 자체 요청 ping및 기타 mysqladmin요청 을보고했습니다 . 쉘에서 데이터베이스를 삭제하려고했기 때문일 수 있습니다. 그러나 해당 명령에 "서버가 사라졌습니다"라는 오류가 계속 발생했습니다. 어쨌든 고마워!
브라이언 피터슨

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