>백엔드 개발 >파이썬 튜토리얼 >Django 데이터베이스 연결 끊김 문제 해결(예제 설명)

Django 데이터베이스 연결 끊김 문제 해결(예제 설명)

不言
不言앞으로
2018-12-29 10:35:433836검색

이 글의 내용은 Django 데이터베이스 연결 끊김 문제를 해결하는 내용입니다(예제 설명). 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

문제

Django에서 mysql을 사용할 때 가끔 데이터베이스 연결이 끊어집니다. 오류에는 일반적으로 다음 두 가지 유형이 포함됩니다.

1. `OperationalError: (2006, 'MySQL server has gone away')`  
1. `OperationalError: (2013, 'Lost connection to MySQL server during query')`

mysql 전역 변수 SHOW GLOBAL VARIABLES를 쿼리하면 이 변수가 연결을 나타냅니다. 유휴 시간. 클라이언트가 하나의 연결을 사용하여 데이터베이스에 여러 번 쿼리하는 경우 쿼리가 연속되면 문제가 없습니다. 여러 쿼리 후에 쿼리가 wait_timeout 이상 일시 중지되면 데이터베이스 연결이 끊어지고 데이터베이스 연결이 끊어집니다.

Reproduction

다음은 Django를 사용하여 다음 번에 문제를 재현합니다.

1. mysql의 wait_timeout을 10초로 설정한 다음 django 쉘을 입력하여 쿼리를 시뮬레이션합니다(다음 오류 메시지 중 일부만) 보유)

In[1]:import time
In[2]:from django.contrib.auth.models import User
In[3]:list(User.objects.filter(id=1))
Out[3]:[<User: admin>]
In[4]:time.sleep(15) # 模拟比较慢的代码(其中没有查询数据库的代码),或者空闲什么都不操作一段时间,此时间要比`wait_timeout`大一些
list(User.objects.filter(id=1))
Traceback (most recent call last):
  File "<ipython-input-4-3574ae8220ee>", line 1, in <module>
    list(User.objects.filter(id=1))

  File "/usr/lib/python3.6/site-packages/pymysql/connections.py", line 1037, in _read_bytes
    CR.CR_SERVER_LOST, "Lost connection to MySQL server during query")
django.db.utils.OperationalError: (2013, 'Lost connection to MySQL server during query')

Seeking

그래서 위의 문제는 기본적으로 유휴 시간이 너무 길어서 발생하는 오류임을 보여줍니다.
불필요한 데이터베이스 연결 및 종료를 줄이기 위해 Django는 요청이 시작되면 연결을 저장하기 위해 연결 풀이 설정되고 이후의 각 요청에 대해 연결이 재사용됩니다. 내 생각엔 Django가 wait_timeout보다 오랫동안 연결을 저장하는 것 같습니다. 저장 시간이 더 짧으면 이 오류를 피하기 위해 연결을 다시 설정할 수 있습니다.
예, 공식 문서에도 이 문제가 설명되어 있습니다. 데이터베이스 CONN_MAX_AGE 매개변수를 설정하세요. 예:

DATABASES = {
    "default": {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': '',
            'USER': '',
            'PASSWORD': '',
            'HOST': '',
            'CONN_MAX_AGE': 9  # 比wait_timeout小一些
    }
}

테스트를 해보니 상황이 생각만큼 간단하지 않다는 것을 알게 되었습니다. 왜 오류가 계속 발생합니까? 이 모든 것의 이면에는 인간 본성의 왜곡이 있는 것인가, 아니면 도덕성의 상실인가. 다음 회 '돌파구'를 시청해 주십시오.

Django 소스 코드의 획기적인

: CONN_MAX_AGE进行了一番搜索,顺藤摸瓜发现了django关闭失效连接的方法django.db.close_old_connections()

# Register an event to reset transaction state and close connections past
# their lifetime.
def close_old_connections(**kwargs):
    for conn in connections.all():
        conn.close_if_unusable_or_obsolete()

signals.request_started.connect(close_old_connections)
signals.request_finished.connect(close_old_connections)
초점은 마지막 두 줄에 있습니다. 이 메서드는 이름에서 알 수 있듯이 특정 이벤트가 구현될 때 실행됩니다. 요청 시작 및 요청 끝. 우리가 보고한 오류는 하나의 요청에 발생했기 때문에 이 방법은 일반적으로 각 요청에 대해 연결을 닫고 다시 설정하기만 하면 됩니다.

반복 문제를 해결하려면 django 쉘을 닫지 말고 다음 코드를 계속 실행하세요.

In[5]:from django.db import close_old_connections
In[6]:close_old_connections()
In[7]:list(User.objects.filter(id=1))
Out[7]: [<User: admin>]
django.db.close_old_connections를 호출한 후 다시 쿼리하면 오류가 발생하지 않습니다.

이 오류를 피하려면 각 데이터베이스 쿼리를 실행하기 전에 django.db.close_old_connections 메서드를 호출해야 합니다.

1. 일반적으로 이러한 문제는 발생하지 않습니다. 왜냐하면 데이터베이스 쿼리는 하나의 요청에 대해 지속적으로 수행되며, 매 요청마다 이 메서드를 호출할 필요가 없기 때문입니다.

2. 때로는 요청에 많은 양의 데이터가 있고 데이터베이스가 쿼리된 다음 일부 데이터를 먼저 쿼리한 후 처리하는 등 일정 시간 동안 다른 처리(데이터베이스와 관련되지 않음)가 수행됩니다. 데이터를 생성하고, 엑셀을 생성하고, 파일을 저장하고, URL을 생성합니다. 이는 매우 오랜 시간이 소요되는 것으로 알려져 있으므로 최종 URL이 데이터베이스에 저장될 때 연결이 끊어지는 것을 방지하기 위해 django.db.close_old_connections를 먼저 호출하는 것이 가장 좋습니다.

위 내용은 Django 데이터베이스 연결 끊김 문제 해결(예제 설명)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제