解决mysql服务器在无操作超时主动断开连接的情况

我们在使用mysql服务的时候,正常情况下,mysql的设置的timeout是8个小时(28800秒),也就是说,如果一个连接8个小时都没有操作,那么mysql会主动的断开连接,当这个连接再次尝试查询的时候就会报个”MySQL server has gone away”的误,但是有时候,由于mysql服务器那边做了一些设置,很多情况下会缩短这个连接timeout时长以保证更多的连接可用。有时候设置得比较变态,很短,30秒,这样就需要客户端这边做一些操作来保证不要让mysql主动来断开。

查看mysql的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: 服务器关闭交互式连接前等待活动的秒数,就是你在你的本机上打开mysql的客户端,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()

这里进行了两次查询,因为我把mysql的wait_timeout设置了30秒,所以我在第一次查询之后停了31秒,目的让mysql服务主动的和我刚才创建的连接断开,得到的结果是

(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'错误。

解决办法

解决的方法有两种,既然这里的超时是由于在规定时间内没有任何操作导致mysql主动的将链接关闭,pymysql的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()

以上这篇解决mysql服务器在无操作超时主动断开连接的情况就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • MySQL 查询速度慢与性能差的原因与解决方法

    一.什么影响了数据库查询速度 1.1 影响数据库查询速度的四个因素 1.2 风险分析 QPS: QueriesPerSecond意思是"每秒查询率",是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准. TPS: 是 TransactionsPerSecond的缩写,也就是事务数/秒.它是软件测试结果的测量单位.客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数. Tips: 最好不要在主库上数据库备

  • python mysql断开重连的实现方法

    后台服务在运行时发现一个问题,运行约15分钟后,接口请求报错 pymysql.err.InterfaceError: (0, '') 这个错误提示一般发生在将None赋给多个值,定位问题时发现 pymysql.err.OperationalError: (2013, 'Lost connection to MySQL server during query') 如何解决这个问题呢 出现问题的代码 class MysqlConnection(object): """ mysql

  • mySQL服务器连接,断开及cmd使用操作

    通过mysql命令实现连接MySQL服务器.在MySQL服务器启动后,选择"开始"→"运行"命令,在弹出的"运行"窗口中输入"cmd"命令,按Enter键后进入DOS窗口,在命令提示符下输入连接MySQL服务器.测试网址 www.dc3688.com 连接MySQL服务器需要输入用户名.密码.MySQL服务器所在地址 >mysql-uroot-h127.0.0.1-ppassword 断开连接 连接到MySQL服务器后,

  • 完美解决MySQL通过localhost无法连接数据库的问题

    问题:一台服务器的PHP程序通过localhost地址无法连接数据库,但是如果设置为127.0.0.1则可以正常连接,连接其他数据库服务器也正常.MySQL的权限设置正确,且通过mysql命令行客户端可以正常连接数据库. 分析:这是典型的socket没有正确设置的情况. 连接MySQL数据库有两种方式:TCP/IP(一般理解的端口的那种)和Unix套接字(一般叫socket或者sock).大部分情况下,可以用localhost代表本机127.0.0.1,但是在MySQL连接时,二者不可混用,而且

  • 解决mysql服务器在无操作超时主动断开连接的情况

    我们在使用mysql服务的时候,正常情况下,mysql的设置的timeout是8个小时(28800秒),也就是说,如果一个连接8个小时都没有操作,那么mysql会主动的断开连接,当这个连接再次尝试查询的时候就会报个"MySQL server has gone away"的误,但是有时候,由于mysql服务器那边做了一些设置,很多情况下会缩短这个连接timeout时长以保证更多的连接可用.有时候设置得比较变态,很短,30秒,这样就需要客户端这边做一些操作来保证不要让mysql主动来断开.

  • 解决Mysql服务器启动时报错问题的方法

    一.概述 文章主要介绍因为启动mysql服务报错引发的问题:"ERROR! The server quit without updating PID file (/var/lib/mysql/localhost.localdomain.pid)",顺带扩充一些其它的知识点,当前版本是red hat 6,mysql 5.6. 二.步骤 报错的源头 问题解决 1.权限 报错的源头就是它了,一般这种问题首先会想到的就是权限问题,就是/var/lib/mysql该文件夹的权限 上图可以看到my

  • 修改配置解决Nginx服务器中常见的上传与连接错误

    nginx上传错误413 Request Entity Too Large 默认情况下使用nginx反向代理上传超过2MB的文件,会报错413 Request Entity Too Large,解决这个方法很简单,修改配置client_max_body_size值即可 修改nginx.conf #cat /usr/local/nginx-1.7.0/conf/nginx.conf | grep client_max_body_size client_max_body_size 10M; 如果需要

  • 具有负载均衡功能的MySQL服务器集群部署及实现

    在实际生产环境中,部署和实现具有一定负载均衡功能的 MySQL服务器集群,对于提高用户数据库应用系统的性能.速度和稳定性具有明显的作用.本文简要介绍了在 FreeBSD 7.0-Release系统上部署实现MySQL服务器集群的方案,并对可能出现的问题提供了相应的解决方法.1. 引言MySQL是一个高速度.高性能.多线程.开放源代码,建立在客户/服务器(Client /Server)结构上的关系型数据库管理系统(RDBMS).它始于1979年,最初是Michael Widenius为瑞典TcX公

  • 简单实现MySQL服务器的优化配置方法

    公司网站访问量越来越大,MySQL自然成为瓶颈,因此最近我一直在研究 MySQL 的优化,第一步自然想到的是 MySQL 系统参数的优化,作为一个访问量很大的网站(日20万人次以上)的数据库系统,不可能指望 MySQL 默认的系统参数能够让 MySQL运行得非常顺畅.以下的文章主要介绍的是对MySQL服务器的优化配置的时机操作步骤,同时本文也介绍了MySQL服务器的优化配置的实际应用代码,如果你对其相关的实际应用感兴趣的话,你就可以点击以下的文章对其进行了解. 你能用这个命令得到MySQL服务器

  • 解决JDBC连接Mysql长时间无动作连接失效的问题

    错误场景介绍 做的有一个项目使用JDBC手动创建Connection实现了一个简单的自定义数据库连接池,用来支持Canal解析数据库Binlog指定业务库的插入修改SQL来进行数据库分表备份(按照月份)操作. 但是发现当一个一段时间(较长)没有进行数据库操作时,连接都失效了,导致SQL执行失败失效提示为No operations allowed after connection closed 查明原因 经过搜索发现这个问题是由于Mysql默认一个已创建的长连接28800秒(八小时)内没有任何动作

  • phpmyadmin报错:#2003 无法登录 MySQL服务器的解决方法

    通过phpmyadmin连接mysql数据库时提示:"2003 无法登录 MySQL服务器"...很明显这是没有启动mysql服务,右击我的电脑-管理-找到服务,找到mysql启动一下,,是不是启动有报错: "无法启动mysql服务 错误1067:进程意外中止 " 然后就baidu google吧,多是说禁远程连接,要改my.ini文件,也有说防火墙的,总之对症下药. 不过同样的报错,导致它的原因并不是都是同样的.这就是看自己的经验和对问题的钻研了,好了不多 说了,

  • 解决 phpmyadmin #2002 无法登录 MySQL 服务器

    解决 .#2002 无法登录 MySQL 服务器 将config.sample.inc.php复制成config.inc.php 出现这个错误,表示没有连接到数据库.修改config.inc.php文件, 复制代码 代码如下: 将$cfg['Servers'][$i]['host'] = 'localhost'; 改为$cfg['Servers'][$i]['host'] = '127.0.0.1'; 或者 修改 php.ini : mysql.default_socket = /tmp/mys

  • MySQL服务器进程CPU占用100%的解决方法

    朋友主机(Windows 2003 + IIS + PHP + MYSQL )近来 MySQL 服务进程 (mysqld-nt.exe) CPU 占用率总为 100% 高居不下.此主机有10个左右的 database, 分别给十个网站调用.据朋友测试,导致 mysqld-nt.exe cpu 占用奇高的是网站A,一旦在 IIS 中将此网站停止服务,CPU 占用就降下来了.一启用,则马上上升. MYSQL CPU 占用 100% 的解决过程 今天早上仔细检查了一下.目前此网站的七日平均日 IP 为

随机推荐