一、参数意思

这里简单解释一下两个参数,含义如下:

  • 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().

  • wait_timeout:The number of seconds the server waits for activity on a noninteractive connection before closing it.
    On
    thread startup, the session wait_timeout 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()).

他们都是session/global级别的,简单的说前者用于描述交互式的客户端的空闲超时,后者用于非交互式的客户端的空闲超时。但是这里也揭示了,如果是交互式客户端连接的session那么wait_timeout将被interactive_timeout覆盖掉,换句话说如果是非交互式的客户端连接的session将不会使用interactive_timeout覆盖掉wait_timeout,也就是interactive_timeout没有任何作用了。

摘自官网内容:

  • 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 globalwait_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_timeout

static Sys_var_ulong Sys_interactive_timeout( vio_io_wait
      "interactive_timeout",
      "The number of seconds the server waits for activity on an interactive "
      "connection before closing it",
      SESSION_VAR(net_interactive_timeout),
      CMD_LINE(REQUIRED_ARG),
      VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(NET_WAIT_TIMEOUT), BLOCK_SIZE(1));

  • wait_timeout

static Sys_var_ulong Sys_net_wait_timeout(
      "wait_timeout",
      "The number of seconds the server waits for activity on a "
      "connection before closing it",
      SESSION_VAR(net_wait_timeout), CMD_LINE(REQUIRED_ARG),
      VALID_RANGE(1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)),
      DEFAULT(NET_WAIT_TIMEOUT), BLOCK_SIZE(1));

我们可以看到内部而言参数interactive_timeout表示为net_interactive_timeoutwait_timeout表示为net_wait_timeout

三、interactive_timeout覆盖wait_timeout

实际上,这个操作只会在用户登陆的时候才出现函数对应server_mpvio_update_thd,如下:

server_mpvio_update_thd(THD *thd, MPVIO_EXT *mpvio) do_command
{
 thd->max_client_packet_length= mpvio->max_client_packet_length;
 if (mpvio->protocol->has_client_capability(CLIENT_INTERACTIVE)) //这里做判断
   thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;//这里覆盖

这里我们可以明确看到有覆盖操作,并且也能看到这里只有if条件是client_interactive类型的客户端连接才会进行覆盖。

栈帧如下:

#0  server_mpvio_update_thd (thd=0x7ffe7c012940, mpvio=0x7fffec0f6140) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/auth/sql_authentication.cc:2014
#1  0x0000000000f01787 in acl_authenticate (thd=0x7ffe7c012940, command=COM_CONNECT, extra_port_connection=false)
   at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/auth/sql_authentication.cc:2246
#2  0x0000000001571149 in check_connection (thd=0x7ffe7c012940, extra_port_connection=false)
   at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_connect.cc:1295
#3  0x00000000015712dc in login_connection (thd=0x7ffe7c012940, extra_port_connection=false)
   at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_connect.cc:1352
#4  0x0000000001571bfe in thd_prepare_connection (thd=0x7ffe7c012940, extra_port_connection=false)
   at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_connect.cc:1516
#5  0x000000000170e642 in handle_connection (arg=0x6781c30) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/conn_handler/connection_handler_per_thread.cc:306

那么,我们这里可以得到一个结论:只在登陆的时候会判断连接是否是交互式的。如果是,则覆盖掉参数wait_timeout,但是一旦连接后将不会发生覆盖操作,即便我们再次修改interactive_timeout的值也不会覆盖,后面我们看到实际上生效的参数只有wait_timeout

四、超时的实现

实际上每次执行任何一个命令都会做一次wait_timeout值的重新检查和给网络read_timeout参数赋值。在函数do_command中我们可以发现步骤my_net_set_read_timeout(net, thd->get_wait_timeout()),这个步骤就是将我们的wait_timeout赋值给网络参数read_timeout,其中包含片段如下:

if (net->read_timeout == timeout) //如果read_timeout和wait_timeout相等
   DBUG_VOID_RETURN;//不需要做操作直接return
 net->read_timeout= timeout;//否则进行赋值。
 if (net->vio)
   vio_timeout(net->vio, 0, timeout);//这里会进行net->vio.read_timeout的赋值

执行完这个步骤后wait_timeout就生效了,然后就会执行命令。执行完命令后,整个线程会再次回到do_command函数,再做一次my_net_set_read_timeout函数,使其中的wait_timeout参数生效,并且阻塞等待接受命令(后面可以看到是poll实现的),这个时候wait_timeout就起作用了。整个栈帧如下:

#0  vio_io_wait (vio=0x7ffe7c015520, event=VIO_IO_EVENT_READ, timeout=10000) at /root/mysqlall/percona-server-locks-detail-5.7.22/vio/viosocket.c:1119
#1  0x0000000001e4d5f6 in vio_socket_io_wait (vio=0x7ffe7c015520, event=VIO_IO_EVENT_READ) at /root/mysqlall/percona-server-locks-detail-5.7.22/vio/viosocket.c:116
#2  0x0000000001e4d6d2 in vio_read (vio=0x7ffe7c015520, buf=0x7ffe7c061c10 "\001", size=4) at /root/mysqlall/percona-server-locks-detail-5.7.22/vio/viosocket.c:171
#3  0x00000000014c6ceb in net_read_raw_loop (net=0x7ffe7c028440, count=4) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/net_serv.cc:672
#4  0x00000000014c6ec2 in net_read_packet_header (net=0x7ffe7c028440) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/net_serv.cc:756
#5  0x00000000014c6fcb in net_read_packet (net=0x7ffe7c028440, complen=0x7fffec0c5c58) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/net_serv.cc:822
#6  0x00000000014c715e in my_net_read (net=0x7ffe7c028440) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/net_serv.cc:899
#7  0x00000000014de010 in Protocol_classic::read_packet (this=0x7ffe7c027bf8) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/protocol_classic.cc:808
#8  0x00000000014de514 in Protocol_classic::get_command (this=0x7ffe7c027bf8, com_data=0x7fffec0c5d70, cmd=0x7fffec0c5d98)
   at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/protocol_classic.cc:965
#9  0x00000000015c5699 in do_command (thd=0x7ffe7c0268e0) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:960

最终会调入vio_io_wait函数,如下是其中的部分片段,我们可以清楚看到实际上所谓的空闲超时实际上就是我们的poll实现的。

switch ((ret= poll(&pfd, 1, timeout)))  
 {
 case -1:
   /* On error, -1 is returned. */
   break;
 case 0:
   /*
     Set errno to indicate a timeout error.
     (This is not compiled in on WIN32.)
   */
   errno= SOCKET_ETIMEDOUT;
   break;
 default:
   /* Ensure that the requested I/O event has completed. */
   DBUG_ASSERT(pfd.revents & revents);
   break;
 }

因此整个步骤就是:

  • loop

  • 做wait_timeout参数检查并且赋值。

  • 阻塞接受命令由poll函数实现,通过poll函数的超时参数也实现了空闲等待超时。(如果不发送命令就阻塞在这里)

  • 命令来到退出阻塞。

  • 再次做wait_timeout参数检查并且赋值。

  • 执行命令。

  • goto loop

五、测试

我这里就用MySQL客户端和PyMySQL进行交互和非交互连接的测试。

  • 交互式MySQL客户端会话interactive_timeout 参数覆盖wait_timeout参数

mysql> show variables like 'wait_timeout%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
1 row in set (0.02 sec)


mysql> show variables like 'interactive_timeout';
+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| interactive_timeout | 28800 |
+---------------------+-------+
1 row in set (0.01 sec)

mysql> set global interactive_timeout = 20;
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Bye
[root@gp1 log]# /mysqldata/mysql3340/bin/mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.22-22-debug-log Source distribution

Copyright (c) 2009-2018 Percona LLC and/or its affiliates
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like 'interactive_timeout';

+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| interactive_timeout | 20    |
+---------------------+-------+
1 row in set (0.01 sec)

mysql> show variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 20    |
+---------------+-------+
1 row in set (0.02 sec)

  • 交互式MySQL客户端会话登陆期间修改interactive_timeout不生效,更改wait_timeout生效。

mysql> show variables like 'interactive_timeout';
+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| interactive_timeout | 28800  |
+---------------------+-------+
1 row in set (0.02 sec)

mysql> show variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800  |
+---------------+-------+
1 row in set (0.02 sec)

mysql> set interactive_timeout=5;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'wait_timeout';

+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800  |
+---------------+-------+
1 row in set (0.01 sec)

mysql> show variables like 'interactive_timeout';
+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| interactive_timeout | 5     |
+---------------------+-------+
1 row in set (0.02 sec)

等待5秒,并未生效
mysql> select sysdate();
+---------------------+
| sysdate()           |
+---------------------+
| 2019-02-28 17:24:29 |
+---------------------+
1 row in set (0.00 sec)

mysql> set wait_timeout=5;
Query OK, 0 rows affected (0.00 sec)

等待5秒 发现断开了
mysql> show variables like 'wait_timeout';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    10

  • 使用Python连接非交互式客户端interactive_timeout 参数不会覆盖wait_timeout参数

我们可以简单的写一个Python脚本如下:

import socket
import pymysql.cursors
import psutil
import subprocess
mysql_con = {"host":"192.168.99.95","port":3340,"user":"pycon","passwd":"gelc123","db":"test"}

def main():
   sqlwait = "show variables like 'wait_timeout'"
   sqlinter = "show variables like 'interactive_timeout'"
   sql_c_inter = "set global interactive_timeout=10"

connect = pymysql.Connect(host=mysql_con["host"], port=mysql_con["port"], user=mysql_con["user"],
                             passwd=mysql_con["passwd"], db=mysql_con["db"])
   cursor = connect.cursor()
   ##查看初始值
   cursor.execute(sqlwait)
   ret_wait = cursor.fetchone()
   cursor.execute(sqlinter)
   ret_inter = cursor.fetchone()
   print("before change: {}".format(ret_wait+ret_inter))

##更改值
   cursor.execute(sql_c_inter)
   connect.close()##关闭连接

##重新登陆开启连接
   connect = pymysql.Connect(host=mysql_con["host"], port=mysql_con["port"], user=mysql_con["user"],
                             passwd=mysql_con["passwd"], db=mysql_con["db"])
   cursor = connect.cursor()

cursor.execute(sqlwait)
   ret_wait = cursor.fetchone()
   cursor.execute(sqlinter)
   ret_inter = cursor.fetchone()

print("after change: {}".format(ret_wait+ret_inter))

##恢复值
   sql_c_inter = "set global interactive_timeout=28800"
   cursor.execute(sql_c_inter)

connect.close()#关闭连接

##程序开始
if __name__ == '__main__':
   main()

得到的测试结果如下:

before change: ('wait_timeout', '28800', 'interactive_timeout', '28800')
after change: ('wait_timeout', '28800', 'interactive_timeout', '10')

如果是交互式,是客户端会话的话wait_timeout也应该是10。

六、总结

  • 内部来讲只有wait_timeout参数会传递到网络层设置,而interactive_timeout参数只会在会话登陆的时候判断是否是交互式客户端会话如果是则进行wait_timeout=interactive_timeout的覆盖,如果不是则不生效的。

  • 一旦会话登陆成功如果想要会话级别修改超时参数,不管交互式还是非交互式都是修改wait_timeout(set wait_timeout)参数才会生效。

  • 内部实现空闲超时是通过poll函数的超时参数实现的。

  • 简单来说interactive_timeout对交互式客户端连接生效,wait_timeout对非交互式客户端连接生效。

  • 对于参数生效的过程如下:

1、loop

2、做wait_timeout参数检查并且赋值。

3、阻塞接受命令由poll函数实现,通过poll函数的超时参数也实现了空闲等待超时。(如果不发送命令就阻塞在这里)

4、命令来到退出阻塞。

5、再次做wait_timeout参数检查并且赋值。

6、执行命令。

7、goto loop

总结

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

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

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

关于“交互式”与“非交互式”连接的区别,请参考:MySQL会话闲置时间控制

转自

知数堂 https://mp.weixin.qq.com/s/sDPEXjpPJqU6AoFV5vmBow

MySQL:参数wait_timeout和interactive_timeout以及空闲超时的实现【转】的更多相关文章

  1. mysql里几个超时配置参数wait_timeout,net_read_timeout等

    以下这些配置项单位都是秒,在mysql命令行中可以使用show global variables like '变量名';可查询配置值. connect_timeout:连接响应超时时间.服务器端在这个 ...

  2. 关于MySQL的wait_timeout连接超时问题报错解决方案

    bug回顾 : 想必大家在用MySQL时都会遇到连接超时的问题,如下图所示: ### Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsExce ...

  3. 关于mysql的wait_timeout参数 设置不生效的问题【转】

    关于wait_timeout 有一次去online set wait_timeout 的时候发现改了不生效,如下: mysql> show variables like 'wait_timeou ...

  4. Mysql参数详解

    1.配置参数 MySQL有两种途径途径了解其的配置参数,一个是MySQL交互模式下的命令SHOW  VARIABLES,一个使用mysqladmin variables 查询. MySQL的配置参数分 ...

  5. wait_timeout 和 interactive_timeout

    wait_timeout 和 interactive_timeout Table of Contents 1. 参数说明 2. 原代码 3. interactive_timeout覆盖wait_tim ...

  6. Java Mysql连接池配置和案例分析--超时异常和处理

    前言: 最近在开发服务的时候, 发现服务只要一段时间不用, 下次首次访问总是失败. 该问题影响虽不大, 但终究影响用户体验. 观察日志后发现, mysql连接因长时间空闲而被关闭, 使用时没有死链检测 ...

  7. MySQL中wait_timeout的坑

    今天遇到了一个问题,一个项目,放到服务器(tomcat)下面的跑,但第二天,总是报错,项目还不能跑 com.mysql.jdbc.exceptions.jdbc4.CommunicationsExce ...

  8. MySQL参数max_connect_errors分析释疑

      最近一MySQL服务器,由于一些特殊因素遇到"ERROR 1129 (00000): Host 'xxx' is blocked because of many connection e ...

  9. MySQL程序之mysql参数详解

    MySQL程序之mysql参数详解 mysql 是一个命令行客户程序,用于交互式或以批处理模式执行SQL语句 用法: mysql [OPTIONS] [database] 参数: 1.-? --hel ...

随机推荐

  1. Divisibility by 25 CodeForces - 988E (技巧的暴力)

    You are given an integer nn from 11 to 10181018 without leading zeroes. In one move you can swap any ...

  2. Kafka如何保证消息的可靠性传输

    1.消费端弄丢了数据 唯一可能导致消费者弄丢数据的情况,就是说,你消费到了这个消息,然后消费者那边自动提交了 offset,让 Kafka 以为你已经消费好了这个消息,但其实你才刚准备处理这个消息,你 ...

  3. MongoDB ODBC Driver for Data Integration with Power BI

    This guide will walk you through connecting Microsoft Power BI to a MongoDB DataSet using our MongoD ...

  4. C#语法相比其它语言比较独特的地方

    C#语法相比其它语言比较独特的地方(一) 本文讲解了switch语句可以用来测试string型的对象.多维数组.foreach语句.索引器和Property等内容 1,switch语句可以用来测试st ...

  5. [模板]fhqTreap

    用途 平衡树(可实现区间翻转) 原理 和treap一样,中序遍历表示权值的顺序,并且每个点有一个随机的附加值,形成一个堆来保证复杂度 但是不旋转,所有操作通过split和merge实现 分为两种spl ...

  6. P4178 Tree(点分治)

    题面要求小于等于K的路径数目,我么很自然的想到点分治(不会的就戳我) 这道题的统计答案与模板题不一样的地方是由等于K到小于等于K 那么我们可以把每一个子节点到当前根(重心)的距离排序,然后用类似双指针 ...

  7. KDJ计算公式

    计算方法编辑KDJ的计算比较复杂,首先要计算周期(n日.n周等)的RSV值,即未成熟随机指标值,然后再计算K值.D值.J值等.以n日KDJ数值的计算为例,其计算公式为n日RSV=(Cn-Ln)/(Hn ...

  8. mysql函数调用过程

    1.conn = mysql_init(NULL);//初始化  MYSQL *conn; 2.mysql_real_connect(conn, "localhost", &quo ...

  9. (模拟 打好基础)nyoj1363-计划日

    1363-计划日 内存限制:256MB 时间限制:3000ms 特判: No通过数:21 提交数:79 难度:1 题目描述: 为什么花那么多时间.精力还是学不好学不通,如何把握各科目的重难点,期中和期 ...

  10. 微信小程序与webview交互实现支付

    实现原理:点击h5网页的支付按钮——(跳转)——>嵌套改h5的小程序的支付页面——(处理支付)——>跳转至支付完成后的页面 注意:(1)网页h5中,引入微信的jssdk <scrip ...