濮阳杆衣贸易有限公司

主頁 > 知識庫 > 解決mysql服務(wù)器在無操作超時主動斷開連接的情況

解決mysql服務(wù)器在無操作超時主動斷開連接的情況

熱門標(biāo)簽:咸陽防封電銷卡 臨沂做地圖標(biāo)注 石家莊400電話辦理公司 廣東400企業(yè)電話申請流程 申請400電話電話價格 地圖標(biāo)注客戶付款 宜賓全自動外呼系統(tǒng)廠家 新鄉(xiāng)智能外呼系統(tǒng)好處 許昌外呼增值業(yè)務(wù)線路

我們在使用mysql服務(wù)的時候,正常情況下,mysql的設(shè)置的timeout是8個小時(28800秒),也就是說,如果一個連接8個小時都沒有操作,那么mysql會主動的斷開連接,當(dāng)這個連接再次嘗試查詢的時候就會報(bào)個”MySQL server has gone away”的誤,但是有時候,由于mysql服務(wù)器那邊做了一些設(shè)置,很多情況下會縮短這個連接timeout時長以保證更多的連接可用。有時候設(shè)置得比較變態(tài),很短,30秒,這樣就需要客戶端這邊做一些操作來保證不要讓mysql主動來斷開。

查看mysql的timeout

使用客戶端工具或者M(jìn)ysql命令行工具輸入show global variables like '%timeout%';就會顯示與timeout相關(guān)的屬性,這里我用docker模擬了一個測試環(huán)境。

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:服務(wù)器關(guān)閉非交互連接之前等待活動的秒數(shù),就是你在你的項(xiàng)目中進(jìn)行程序調(diào)用

interactive_timeout: 服務(wù)器關(guān)閉交互式連接前等待活動的秒數(shù),就是你在你的本機(jī)上打開mysql的客戶端,cmd的那種

使用pymysql進(jìn)行查詢

我在數(shù)據(jù)庫里隨便創(chuàng)建了一個表,插入兩條數(shù)據(jù)

mysql> select * from person;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | yang | 18 |
| 2 | fan | 16 |
+----+------+-----+
2 rows in set

我使用pymysql這個庫對其進(jìn)行查詢操作,很簡單

#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()

可以正確的得到結(jié)果

(1, 'yang', 18)

(2, 'fan', 16)

連接超時以后的查詢

上面可以正常得到結(jié)果是由于當(dāng)創(chuàng)建好一個鏈接以后,就立刻進(jìn)行了查詢,此時還沒有超過它的超時時間,如果我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()

這里進(jìn)行了兩次查詢,因?yàn)槲野裮ysql的wait_timeout設(shè)置了30秒,所以我在第一次查詢之后停了31秒,目的讓mysql服務(wù)主動的和我剛才創(chuàng)建的連接斷開,得到的結(jié)果是

(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秒鐘以后,再次使用該連接進(jìn)行查詢將拋出2013, 'Lost connection to MySQL server during query'錯誤。

解決辦法

解決的方法有兩種,既然這里的超時是由于在規(guī)定時間內(nèi)沒有任何操作導(dǎo)致mysql主動的將鏈接關(guān)閉,pymysql的connection對象有一個ping()方法,可以檢查連接是否有效,在每次執(zhí)行查詢操作之前先執(zhí)行一下ping()方法,該方法默認(rèn)的有個reconnect參數(shù),默認(rèn)是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()

我曾嘗試使用另外一個線程不停來執(zhí)行ping()操作,但是當(dāng)我這樣做以后連接就會丟失,之后的操作就不能進(jìn)行了。這個問題我再研究研究。

#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之后再運(yùn)行才可以
  # 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()

還有一種方法是使用連接池,連接池中保持著指定數(shù)量的可用連接,每次重新獲取一個有效的連接進(jìn)行查詢操作,pymysql本身不具有連接池功能,需要借住DBUtils

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


def mytest():
  pool = PooledDB(
    creator=pymysql,
    # 初始化時,連接池至少創(chuàng)建的空閑連接,0表示不創(chuàng)建
    maxconnections=3, 
    # 連接池中空閑的最多連接數(shù),0和None表示沒有限制    
    mincached=2,
    # 連接池中最多共享的連接數(shù)量,0和None表示全部共享(其實(shí)沒什么卵用)
    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()

這種方式雖然可以正確的獲取結(jié)果,但是實(shí)際的項(xiàng)目中并不會這么使用,而是在執(zhí)行完查詢語句以后要將connection關(guān)閉,注意這里的關(guān)閉并不是真正的關(guān)閉,而只是將連接返回給連接池讓其它人使用.

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


def mytest():
  pool = PooledDB(
    creator=pymysql,
    maxconnections=3,
    # 初始化時,連接池至少創(chuàng)建的空閑連接,0表示不創(chuàng)建
    mincached=2,
    # 連接池中空閑的最多連接數(shù),0和None表示沒有限制
    maxcached=5,
    # 連接池中最多共享的連接數(shù)量,0和None表示全部共享(其實(shí)沒什么卵用)
    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()
  # 關(guān)閉連接,其實(shí)并沒有真正關(guān)閉,只是將連接返回給連接池
  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()

以上這篇解決mysql服務(wù)器在無操作超時主動斷開連接的情況就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

您可能感興趣的文章:
  • 小程序server請求微信服務(wù)器超時的解決方法
  • php中curl和soap方式請求服務(wù)超時問題的解決
  • 淺談java中異步多線程超時導(dǎo)致的服務(wù)異常
  • 詳解Nginx服務(wù)器中配置超時時間的方法
  • Win7系統(tǒng)日志提示在沒有配置的 DNS 服務(wù)器響應(yīng)之后,名稱“域名”的名稱解析超時的解放方法
  • oracle遠(yuǎn)程連接服務(wù)器出現(xiàn) ORA-12170 TNS:連接超時 解決辦法
  • 使用FileZilla連接時超時無法連接到服務(wù)器
  • SNMP4J服務(wù)端連接超時問題解決方案

標(biāo)簽:北京 鎮(zhèn)江 鷹潭 合肥 貴州 臺灣 阜新 日照

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《解決mysql服務(wù)器在無操作超時主動斷開連接的情況》,本文關(guān)鍵詞  解決,mysql,服務(wù)器,在,無,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《解決mysql服務(wù)器在無操作超時主動斷開連接的情況》相關(guān)的同類信息!
  • 本頁收集關(guān)于解決mysql服務(wù)器在無操作超時主動斷開連接的情況的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    德格县| 万安县| 宁波市| 太仆寺旗| 宁安市| 屯门区| 浪卡子县| 宝坻区| 民乐县| 米易县| 乐陵市| 喀什市| 淮阳县| 阳原县| 东宁县| 韶山市| 澄城县| 义马市| 武宣县| 通渭县| 商南县| 石景山区| 延津县| 江陵县| 公安县| 内江市| 黎川县| 武邑县| 马公市| 金阳县| 阿城市| 达州市| 拜城县| 益阳市| 定边县| 仙游县| 申扎县| 英德市| 荥经县| 洛南县| 叶城县|