mysql 서버 가 무 동작 시간 초과 로 주동 적 으로 연결 을 끊 는 상황 을 해결 합 니 다

우리 가 my sql 서 비 스 를 사용 할 때 정상 적 인 상황 에서 my sql 설정 의 timeout 은 8 시간(28800 초)입 니 다.즉,한 연결 이 8 시간 동안 작 동 하지 않 으 면 my sql 은 주동 적 으로 연결 을 끊 습 니 다.이 연결 이 다시 검색 을 시도 할 때'MySQL server has gone away'의 오 류 를 보고 합 니 다.그러나 가끔 은...my sql 서버 쪽 에서 설정 을 했 기 때문에 이 연결 시간 을 단축 시 켜 더 많은 연결 을 사용 할 수 있 도록 하 는 경우 가 많 습 니 다.가끔 은 변태 적 으로 설정 되 어 있 습 니 다.아주 짧 고 30 초 입 니 다.그러면 클 라 이언 트 쪽 에서 my sql 이 자발적으로 끊 지 않도록 조작 을 해 야 합 니 다.
my sql timeout 보기
클 라 이언 트 도구 나 Mysql 명령 행 도 구 를 사용 하여 show global variables like'%timeout%'를 입력 하 십시오.timeout 과 관련 된 속성 이 표 시 됩 니 다.여 기 는 docker 로 테스트 환경 을 모 의 했 습 니 다.

mysql> show variables like '%timeout%'; 
+-----------------------------+----------+
| Variable_name        | Value  |
+-----------------------------+----------+
| connect_timeout       | 10    |
| delayed_insert_timeout   | 300   |
| have_statement_timeout   | YES   |
| innodb_flush_log_at_timeout | 1    |
| innodb_lock_wait_timeout  | 50    |
| innodb_rollback_on_timeout | OFF   |
| interactive_timeout     | 30    |
| lock_wait_timeout      | 31536000 |
| net_read_timeout      | 30    |
| net_write_timeout      | 60    |
| rpl_stop_slave_timeout   | 31536000 |
| slave_net_timeout      | 60    |
| wait_timeout        | 30    |
+-----------------------------+----------+
13 rows in set
wait_timeout:서버 가 비 상호작용 연결 을 닫 기 전에 활동 을 기다 리 는 초 수 는 프로젝트 에서 프로그램 호출 을 하 는 것 입 니 다.
interactive_timeout:서버 가 대화 식 연결 을 닫 기 전에 활동 을 기다 리 는 초 수 는 바로 이 컴퓨터 에서 my sql 클 라 이언 트,cmd 를 여 는 것 입 니 다.
pymysql 로 조회 하기
나 는 데이터베이스 에 마음대로 표를 만 들 고 두 개의 데 이 터 를 삽입 했다.

mysql> select * from person;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | yang | 18 |
| 2 | fan | 16 |
+----+------+-----+
2 rows in set
나 는 pymysql 라 이브 러 리 를 사용 하여 그것 을 조회 하 는데 매우 간단 하 다

#coding:utf-8
import pymysql

def mytest():
  connection = pymysql.connect(
  host='localhost',
  port=3306,
  user='root',
  password='123456',
  db='mytest',
  charset='utf8')

  cursor = connection.cursor()
  cursor.execute("select * from person")
  data = cursor.fetchall()
  cursor.close()
  for i in data:
    print(i)
  cursor.close()
  connection.close()

if __name__ == '__main__':
  mytest()
정확 한 결 과 를 얻 을 수 있 습 니 다.
(1, 'yang', 18)
(2, 'fan', 16)
연결 시간 초과 후 검색
위 에서 정상적으로 결 과 를 얻 을 수 있 는 것 은 링크 를 만 든 후에 바로 조 회 를 했 기 때 문 입 니 다.이때 시간 초과 시간 을 초과 하지 않 았 기 때 문 입 니 다.만약 에 제 가 sleep 를 한 동안 하면 어떤 효 과 를 볼 수 있 습 니까?

#coding:utf-8

import pymysql
import time


def mytest():
  connection = pymysql.connect(
  host='localhost',
  port=3306,
  user='root',
  password='123456',
  db='mytest',
  charset='utf8')
  cursor = connection.cursor()
  cursor.execute("select * from person")
  data = cursor.fetchall()
  for i in data:
    print(i)
  cursor.close()

  time.sleep(31)
  cursor = connection.cursor()
  cursor.execute("select * from person")
  data2 = cursor.fetchall()
  for i in data2:
    print(i)
  cursor.close()
  connection.close()

if __name__ == '__main__':
  mytest()
내 가 my sql 의 wait 를timeout 은 30 초 동안 설정 되 어 있 습 니 다.그래서 저 는 첫 번 째 조회 후에 31 초 동안 멈 추 었 습 니 다.목적 은 my sql 서비스 가 주동 적 으로 제 가 방금 만 든 연결 과 끊 기 고 얻 은 결 과 는?

(1, 'yang', 18)
(2, 'fan', 16)
Traceback (most recent call last):
 File "F:/python/python3Test/mysqltest.py", line 29, in <module>
  mytest()
 File "F:/python/python3Test/mysqltest.py", line 22, in mytest
  cursor.execute("select * from person")
 ...
 ...
 File "C:\Python35\lib\site-packages\pymysql\connections.py", line 702, in _read_bytes
  CR.CR_SERVER_LOST, "Lost connection to MySQL server during query")
pymysql.err.OperationalError: (2013, 'Lost connection to MySQL server during query')

Process finished with exit code 1
31 초 간 멈 춘 후에 이 연결 을 다시 사용 하여 조회 하면 2013,'Lost connection to MySQL server during query'오류 가 발생 합 니 다.
해결 방법
해결 방법 은 두 가지 가 있 습 니 다.시간 초과 가 규정된 시간 내 에 어떠한 조작 도 하지 않 았 기 때문에 my sql 이 주동 적 으로 링크 를 닫 았 습 니 다.pymy sql 의 connection 대상 은 ping()방법 이 있 습 니 다.연결 이 효과 적 인지 확인 할 수 있 습 니 다.매번 조회 작업 을 수행 하기 전에 ping()방법 을 실행 할 수 있 습 니 다.이 방법 은 기본적으로 reconnect 파라미터 가 있 습 니 다.기본 값 은 True 입 니 다.연결 을 잃 으 면 다시 연 결 됩 니 다.

#coding:utf-8

import pymysql
import time


def mytest():
  connection = pymysql.connect(
  host='localhost',
  port=3306,
  user='root',
  password='123456',
  db='mytest',
  charset='utf8')
  connection.ping()
  cursor = connection.cursor()
  cursor.execute("select * from person")
  data = cursor.fetchall()
  for i in data:
    print(i)
  cursor.close()
  
  time.sleep(31)
  connection.ping()
  cursor = connection.cursor()
  cursor.execute("select * from person")
  data2 = cursor.fetchall()
  for i in data2:
    print(i)
  cursor.close()
  connection.close()

if __name__ == '__main__':
  mytest()
나 는 다른 스 레 드 를 사용 하여 ping()작업 을 계속 실행 하려 고 시 도 했 지만,내 가 이렇게 하면 연결 이 잃 어 버 리 고 그 후의 작업 은 진행 할 수 없다.이 문 제 는 내 가 다시 연구 하 겠 다.

#coding:utf-8

import pymysql
import time
import threading
import traceback

def ping(conn):
  while True:
    try:      
      conn.ping()
    except:
      print(traceback.format_exc())
    finally:
      time.sleep(1)

def mytest():
  connection = pymysql.connect(
  host='localhost',
  port=3306,
  user='root',
  password='123456',
  db='mytest',
  charset='utf8')
  cursor = connection.cursor()
  #       ,    cursor   execute        
  # th = threading.Thread(target=ping, args=(connection,))
  # th.setDaemon(True)
  # th.start()
  cursor.execute("select * from person")
  data = cursor.fetchall()
  for i in data:
    print(i)
  cursor.close()

  #           
  th = threading.Thread(target=ping, args=(connection,))
  th.setDaemon(True)
  th.start()
  
  time.sleep(31)
  cursor = connection.cursor()
  cursor.execute("select * from person")
  data2 = cursor.fetchall()
  for i in data2:
    print(i)
  cursor.close()
  connection.close()

if __name__ == '__main__':
  mytest()
또 하나의 방법 은 연결 탱크 를 사용 하 는 것 입 니 다.연결 탱크 에 지 정 된 수량의 사용 가능 한 연결 을 유지 하고 있 습 니 다.매번 에 효과 적 인 연결 을 다시 가 져 와 조회 작업 을 하 는 것 입 니 다.pymysql 자 체 는 연결 탱크 기능 이 없 기 때문에 DBUtils 를 빌려 야 합 니 다.

#coding:utf-8
import pymysql
import time
from DBUtils.PooledDB import PooledDB, SharedDBConnection


def mytest():
  pool = PooledDB(
    creator=pymysql,
    #     ,            ,0     
    maxconnections=3, 
    #             ,0 None          
    mincached=2,
    #              ,0 None      (       )
    maxcached=5,    
    maxshared=3,
    host='localhost',
    port=3306,
    user='root',
    password='123456',
    db='mytest',
    charset='utf8'
  )
  connection = pool.connection()
  cursor = connection.cursor()
  cursor.execute("select * from person")
  data = cursor.fetchall()
  for i in data:
    print(i)

  time.sleep(40)
  cursor.execute("select * from person")
  data2 = cursor.fetchall()
  for i in data2:
    print(i)
  cursor.close()
  connection.close()

if __name__ == '__main__':
  mytest()
이러한 방식 은 결 과 를 정확하게 얻 을 수 있 지만 실제 항목 에 서 는 이렇게 사용 되 지 않 습 니 다.검색 어 를 실행 한 후에 connection 을 닫 아야 합 니 다.여기 서 닫 는 것 은 실제 닫 는 것 이 아니 라 연결 풀 에 연결 을 되 돌려 다른 사람 이 사용 하도록 하 는 것 입 니 다.

#coding:utf-8
import pymysql
import time
from DBUtils.PooledDB import PooledDB, SharedDBConnection


def mytest():
  pool = PooledDB(
    creator=pymysql,
    maxconnections=3,
    #     ,            ,0     
    mincached=2,
    #             ,0 None      
    maxcached=5,
    #              ,0 None      (       )
    maxshared=3,
    host='localhost',
    port=3306,
    user='root',
    password='123456',
    db='mytest',
    charset='utf8'
  )
  connection = pool.connection()
  cursor = connection.cursor()
  cursor.execute("select * from person")
  data = cursor.fetchall()
  for i in data:
    print(i)
  cursor.close()
  #     ,         ,           
  connection.close()

  time.sleep(40)
  connection = pool.connection()
  cursor = connection.cursor()
  cursor.execute("select * from person")
  data2 = cursor.fetchall()
  for i in data2:
    print(i)
  cursor.close()
  connection.close()

if __name__ == '__main__':
  mytest()
이 문 제 는 my sql 서버 가 무 조작 시간 초과 로 자발적으로 연결 을 끊 는 상황 을 해결 하 는 것 입 니 다.바로 작은 편집 이 여러분 에 게 공유 하 는 모든 내용 입 니 다.참고 하 시기 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기