导读

作者魏新平

现象

当我们用MySQL客户端或者程序(如Java,Python等)连接MySQL后,如果闲置一段时间(就是不执行任何SQL),再次执行SQL的时候就会报失去连接的错误,如:

ERROR 2006 (HY000): MySQL server has gone away

Lost connection to MySQL server during query

这是MySQL控制连接数的机制,会自动把一些闲置时间超过配置值的连接kill掉。

闲置时间配置参数

这里涉及的参数有两个,wait_timeout 和 interactive_timeout。而MySQL的参数又分为GLOBAL级别和SESSION级别,所以严格的讲,会涉及到四个参数。

参数的官方解释:

  • interactive_timeout: The number of seconds the server waits for activity on an interactive connection before closing it. An interactive client is defined as a client that uses the CLIENT_INTERACTIVE option to mysql_real_connect().
    翻译:interactive_timeout控制交互式连接的空闲时间,如果调用mysql的mysql_real_connect()函数的时候,使用了CLIENT_INTERACTIVE参数,该连接就定义为交互式连接。
  • wait_timeout: The number of seconds the server waits for activity on a noninteractive connection before closing it.
    翻译:wait_timeout控制非交互连接的闲置时间。
  • On thread startup, the session waittimeout value is initialized from the global wait_timeout value or from the global interactive_timeout value, depending on the type of client (as defined by the CLIENT_INTERACTIVE connect option to mysql_real_connect()). See also interactive_timeout.
    翻译:在连接建立的时候,session级别的wait_timeout会根据连接的分类来选择是继承global级别的interactive_timeout的值和global级别的wait_timeout的值。

看完官方针对interactive_timeoutwait_timeout的解释,其实会发现写的挺让人难以理解的,没有讲清楚SESSION级别和GLOBAL级别的两个参数是如何控制连接的闲置时间的,而且很难区分什么是交互式连接,什么是非互式连接,只能从源代码层面去区分。

接下来我们平常使用的连接方式来做实验(使用的MySQL版本为Percona的MySQL5.7)。

实验一:

先分别设置GLOBAL级别的interactive_timeoutwait_timeout

pymysql 断开连接 pymysql连接超时时间_mysql

1、重新用MySQL客户端开一个窗口,查看SESSION参数

pymysql 断开连接 pymysql连接超时时间_pymysql连接mysql_02

可以看出SESSION级别的wait_timeoutinteractive_timeout都继承了GLOBAL.interactive_timeout的值,也就是说mysql客户端属于交互式连接。

2、用PyMySQL查看参数值(Python3版本)

pymysql 断开连接 pymysql连接超时时间_mysql_03

结果为

{'@@GLOBAL.interactive_timeout': 20, '@@GLOBAL.wait_timeout': 40, '@@session.interactive_timeout': 20, '@@session.wait_timeout': 40}

结论:SESSION级别的wait_timeoutinteractive_timeout继承了各自的GLOBAL级别的值,也就是说Python的Pymysql连接被定义为非交互式连接。

实验二:

1、MySQL官方客户端

pymysql 断开连接 pymysql连接超时时间_MySQL_04

然后用同样的方式去测试剩下的三个参数,发现只有修改SESSION级别的wait_timeout才会有

 ERROR 2006 (HY000): MySQL server has gone away

错误(请务必在同一个会话当中测试)。

2、Pymysql(Python3)

pymysql 断开连接 pymysql连接超时时间_pymysql连接mysql_05

用另外3个参数来运行上述代码,只有修改session级别wait_timeout才会出现如下错误:

pymysql.err.OperationalError: (2013, 'Lost connection to MySQL server during query')

结论:从实验二可以看出,针对已经存在的连接来说,交互式和非交互式连接的闲置时间都是由SESSION级别的wait_timeout控制的。

总结

1、交互式连接和非交互式连接的空闲时间都是由SESSION级别的wait_timeout时间控制的

2、SESSION级别的wait_timeout值是再连接初始化的时候,根据连接的分类来确定是从GLOBAL 级别的interactive_timeout值继承还是GLOBAL级别的wait_timeout值继承

3、SESSION级别的interactive_timeout对连接的闲置时间没有用处

pymysql 断开连接 pymysql连接超时时间_修改网站自动关闭时间timeout_06