Django, 업그레이드 후:내 SQL 서버가 사라졌습니다.
최근에 Django 1.4에서 Django 1.7로 업그레이드했는데 일부 스크립트에 대해 다음 오류 메시지가 계속 뜨기 때문에 때때로 다음과 같은 메시지가 나타납니다.
OperationalError: (2006, 'MySQL server has gone away')
스크립트가 매우 길거나 계속 실행 중인 작업으로, 몇 분 동안 DB와 통신하지 않는 단계가 수반되어 연결 시간이 초과됩니다.하지만 제가 업그레이드하기 전에 장고가 자동적으로 연결을 다시 설정하는 것 같았기 때문에 문제가 되지 않았습니다.이제 작업이 중단되고 중간에 실패하는 경우가 많다는 의미는 아닙니다.
무엇이 바뀌었는지 그리고 어떻게 고칠 수 있는지 아는 사람?
티켓/수정과 관련이 있습니까? https://code.djangoproject.com/ticket/21463
정말 고마워.
이러한 동작의 이유는 장고 1.6에서 도입된 데이터베이스에 대한 지속적인 연결 때문입니다.
시간 하려면 를(를) .CONN_MAX_AGE
인에settings.py
을 매기다wait_timeout
MySQL성()my.cnf
이 경우 Django는 MySQL이 생성하는 것보다 먼저 연결을 다시 열어야 함을 감지합니다.MySQL 5.7의 기본값은 28800초입니다.
settings.py
:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'CONN_MAX_AGE': 3600,
<other params here>
}
}
문서: https://docs.djangoproject.com/en/1.7/ref/settings/ #conn-max-age
my.cnf
:
wait_timeout = 28800
문서: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_wait_timeout
가 실행 입니다.rqworker
일부 사용자 작업 후 일부 데이터를 새로 고치기 위해 별도의 작업을 실행합니다.
에 .OperationalError: (2006, 'MySQL server has gone away')
wait_timeout
.초. CONN_MAX_AGE를 MySQL보다 wait_timeout
.
제가 알기로는, 장고가 이 타임아웃까지 자동으로 연결을 확인하고 닫는다면 CONN_MAX_AGE 변경이 도움이 될 것 같습니다.그러나 Django 1.7.x는 각 요청 전후에만 확인합니다(django/db/init.py#L101-L112 참조).
장고 티켓 15119에 나와 있는 것처럼, 우리는 장고가 모든 쿼리를 실행하기 전에 연결이 살아 있는지 확인하기 위해 핑을 하고 있었음을 알 수 있습니다.이 동작은 커밋 282b2f4에서 수정되었습니다.
장고 개발자들은 https://code.djangoproject.com/ticket/21597#comment:29 에서 이와 같은 모든 질문에 대해 짧은 답변을 하나 했습니다.
의 rqworker
프로세스는 각 새 작업에 대해 연결 자체를 검증해야 합니다.가 새 (참고: 연결을 닫으면 장고가 새 연결을 만듭니다.)
리퀘스트 를 구하고 입니다를 django.db.close_old_connections()
모든 일의 전후에그리고 네.CONN_MAX_AGE
MySQL.wait_timeout
, 왜냐하면 장고는 확인을 안하기 때문입니다.MySQL server has gone away
인에django.db.close_old_connections()
방법.
장고 1.9에서: 유닉스 화면에서 진행 중인 장고 셸을 48시간 이상 방치했습니다.내가 그 곳으로 돌아와서 달려갔을 때<some_model>.objects.filter
던졌습니다.OperationalError: (2006, 'MySQL server has gone away')
import django.db; django.db.close_old_connections()
나를 위해 속임수를 썼답니다.
에 대한 를 찾을 수 close_old_connections()
1.9 용 장고 문서에서 하지만 여기 깃허브의 장고 코드베이스에서 구현된 직접적인 링크가 있습니다.
django 1.6에서 wait_timeout이 경과하면 (mysql의) DB 액세스로 인해 (2006년 'MySQL 서버가 사라졌습니다') 오류가 발생합니다.장고 1.5.1에서는 그렇지 않았습니다.
장고 코드를 실행하는 작업자(기어맨 사용)를 사용할 때 이 오류를 발견했습니다.
재생하는 방법:
[mysql]에서 /etc/mysql/my.cnf를 편집하여 제한 시간을 낮은 값으로 설정합니다.
wait_timeout = 10
interactive_timeout = 10
그리고나서
% python manage피조개
>>> # access DB
>>> import django.contrib.auth.models
>>> print list(django.contrib.auth.models.User.objects.all())
>>> import time
>>> time.sleep(15)
>>> print list(django.contrib.auth.models.User.objects.all())
이제 오류를 알 수 있습니다.
웹에서 찾은 간단한 해결책은 접속 전에 django.db.close_connection()을 호출하는 것입니다.
>>> import django.db
>>> django.db.close_connection()
>>> print list(django.contrib.auth.models.User.objects.all())
일이 잘 됩니다.
저희도 눈치챘어요.위의 답변은 웹에 대해 CONN_MAX_AGE를 MySQL / MariaDB의 wait_timeout보다 작은 것으로 설정하는 것입니다.
오랫동안 실행 중인 작업의 경우에는 이 작업이 작동하지 않는 것 같습니다.대신에 우리는 오래 실행 중인 작업 중 하나가 실행될 때마다 그것을 포장하고 연결을 닫습니다.
우리는 이것을 자체 맞춤형 풀과 결합합니다.가져가든, 놔두든 - 기본적인 Django one은 통제력이 전혀 없습니다 - 우리가 제작에서 좋아했던 것이 아닙니다.서버가 너무 많은 연결로 DB를 죽이기 전에 서버를 죽일 수 있는 최대 풀을 설정했습니다.작업을 위한 장식 도구로 사용:
@close_db_connection()
def task_do_something():
print 'Hello'
'''
Created on Dec 23, 2017
@author: Kevin
'''
from functools import wraps
def close_db_connection(ExceptionToCheck=Exception, raise_exception=False, notify=False):
"""Close the database connection when we're finished, django will have to get a new one..."""
def deco_wrap(f):
@wraps(f)
def f_wrap(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
raise e
finally:
from django.db import connection;
connection.close();
return f_wrap
return deco_wrap
쇼트:
pip install mysql_server_has_gone_away
설정.py:
DATABASES = {
'default': {
'ENGINE': 'mysql_server_has_gone_away'
}
}
TL;DR
저의 경우는 장고 ORM을 사용하고 있었고, long living request(webocket)를 사용하고 있었습니다.CONN_MAX_AGE
제 경우에는 통하지 않습니다.
처음에는 오류를 잡아보려고 포장지를 만들었지만 장고가 귀찮아서 어떤 물건으로 포장해야 할지 잘 모르겠습니다.그래서 프로젝트 전반에 걸쳐 이 코드를 복제하게 되었는데 그건 일종의 골칫거리였습니다.예를 에를 .User.objects.get(id=3)
다를 할.do_db(User.objects.get, id=3)
고 db였습니다.try: return callback(*args, **kwargs); catch e: conn.close(); callback(*args, **kwargs)
.
장고 백엔드를 파고들 때 이 솔루션을 연결 수준으로 마이그레이션할 수 있습니다.따라서 db로 가는 모든 쿼리는 다음과 같이 래핑됩니다.
설정.py:
DATABASES = {
'default': {
'ENGINE': 'lol'
}
}
lol/base.py:
"""
https://stackoverflow.com/a/60894948/3872976
"""
from django.db.backends.mysql import base
def check_mysql_gone_away(db_wrapper):
def decorate(f):
def wrapper(self, query, args=None):
try:
return f(self, query, args)
except (base.Database.OperationalError, base.Database.InterfaceError) as e:
if 'MySQL server has gone away' in str(e):
db_wrapper.connection.close()
db_wrapper.connect()
self.cursor = db_wrapper.connection.cursor()
return f(self, query, args)
# Map some error codes to IntegrityError, since they seem to be
# misclassified and Django would prefer the more logical place.
if e.args[0] in self.codes_for_integrityerror:
raise base.utils.IntegrityError(*tuple(e.args))
raise
return wrapper
return decorate
class DatabaseWrapper(base.DatabaseWrapper):
def create_cursor(self, name=None):
class CursorWrapper(base.CursorWrapper):
@check_mysql_gone_away(self)
def execute(self, query, args=None):
return self.cursor.execute(query, args)
@check_mysql_gone_away(self)
def executemany(self, query, args):
return self.cursor.executemany(query, args)
cursor = self.connection.cursor()
return CursorWrapper(cursor)
원자력 작동 중에 mysql 연결이 끊어지면 거래에 문제가 생길 수 있다는 점에 유의해야 합니다.하지만 불행히도 다른 방법이 없습니다.
아마도 타임아웃은 몇몇 사람들에게 문제가 될 수 있지만 매우 큰 BLOB 필드를 작성하려고 할 때 이 문제에 부딪혔습니다.mysql 구성 파일에서 허용되는 최대 패킷 크기를 늘려서 해결했습니다...
max_allowed_packet=4M
/etc/my.cnf로 변경한 후 mysql을 다시 시작하는 것을 잊지 마십시오.이 페이지는 도움이 됐습니다...
http://dev.mysql.com/doc/refman/5.5/en/packet-too-large.html
저는 제 해결책이 어디에 있는지 같은 문제에 직면해 있었습니다.저는 장고에 처음 와서 이미 늦었지만 해결책을 올립니다.누군가에게 도움이 될지도 모릅니다.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'your_dabase',
'USER': 'your_user',
'PASSWORD': 'your_password',
'HOST': 'your_host',
'PORT': 'your_port',
'CONN_MAX_AGE': 290,
},
'OPTIONS': {
'timeout':20,
}
}
CONN_MAX_AGE와 OPTIONS를 추가했고 현재 완벽하게 작동하고 있습니다.
이것이 오래된 질문이라는 것을 알고 있지만, 제 경우의 해결책은 현재의 어떤 대답에도 없었습니다.
제 문제의 근원은 서버 쪽에 있었습니다.서버 시간 초과 설정 확인(사용)show global variables like '%timeout'
) 제가 알게 된 것은wait_timeout
변수가 120초로 설정되어 있으므로 데이터를 검색하거나 저장하려고 할 때 이 시간이 걸리는 작업은 '서버가 사라졌습니다'라는 예외가 발생합니다.추가하기CONN_MAX_AGE
아무런 차이가 없었습니다.
솔루션 #1 - 서버의 wait_timeout 설정 변경(권한이 있는 경우)
사용하다set global wait_timeout=1*60*60
시간은 초 단위로 제공됩니다.
솔루션 #2 - db 유휴 시간 후 새 연결 강제 수행
Django 보기/태스크에서:
from django.db import connection
from django.db.utils import OperationalError
cursor = connection.cursor()
cursor.execute('SELECT 1') # <-- no issues here
# time consuming code...
try:
cursor.execute('SELECT 1')
except OperationalError:
connection.connect()
cursor = connection.cursor()
cursor.execute('SELECT 1')
관찰:
이것은 ORM 요청에도 적용되어야 합니다.
장고 버전 3.1.6
고치다OperationalError: (2006, 'MySQL server has gone away')
위해서Django >= 4.1
장고 설정을 업데이트 할 수 있습니다.
- 데이터베이스에 대한 영구 연결 사용 및 CONN_MAX_AGE 설정
DATABASES = {
'default': {
....
'CONN_MAX_AGE': 60, # value must be less then your Mysql `interactive_timeout`/`wait_timeout`
}}
- 영구 연결 재사용에 대해 상태 검사를 사용하도록 설정하고 CONN_HEalth_CHECKs를 설정합니다.
DATABASES = {
'default': {
....
'CONN_HEALTH_CHECKS': True,
}}
각 db 요청에 대한 결과Django
s 를 확인하고, ping에서 지"s _usable)면 Django다가 됩니다.
언급URL : https://stackoverflow.com/questions/26958592/django-after-upgrade-mysql-server-has-gone-away
'programing' 카테고리의 다른 글
네이티브 앱에서 하이퍼링크를 표시하는 방법은? (0) | 2023.10.01 |
---|---|
말이 되는 자바스크립트 퍼지 검색 (0) | 2023.10.01 |
팬더 데이터 프레임의 문자열 열에서 텍스트를 대체하는 방법은 무엇입니까? (0) | 2023.09.26 |
jquery clone div 및 특정 div 뒤에 추가 (0) | 2023.09.26 |
목록 항목 사이에 세로 공간을 설정하려면 어떻게 해야 합니까? (0) | 2023.09.26 |