MySQL:参数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().
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_timeout,wait_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以及空闲超时的实现【转】的更多相关文章
- mysql里几个超时配置参数wait_timeout,net_read_timeout等
以下这些配置项单位都是秒,在mysql命令行中可以使用show global variables like '变量名';可查询配置值. connect_timeout:连接响应超时时间.服务器端在这个 ...
- 关于MySQL的wait_timeout连接超时问题报错解决方案
bug回顾 : 想必大家在用MySQL时都会遇到连接超时的问题,如下图所示: ### Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsExce ...
- 关于mysql的wait_timeout参数 设置不生效的问题【转】
关于wait_timeout 有一次去online set wait_timeout 的时候发现改了不生效,如下: mysql> show variables like 'wait_timeou ...
- Mysql参数详解
1.配置参数 MySQL有两种途径途径了解其的配置参数,一个是MySQL交互模式下的命令SHOW VARIABLES,一个使用mysqladmin variables 查询. MySQL的配置参数分 ...
- wait_timeout 和 interactive_timeout
wait_timeout 和 interactive_timeout Table of Contents 1. 参数说明 2. 原代码 3. interactive_timeout覆盖wait_tim ...
- Java Mysql连接池配置和案例分析--超时异常和处理
前言: 最近在开发服务的时候, 发现服务只要一段时间不用, 下次首次访问总是失败. 该问题影响虽不大, 但终究影响用户体验. 观察日志后发现, mysql连接因长时间空闲而被关闭, 使用时没有死链检测 ...
- MySQL中wait_timeout的坑
今天遇到了一个问题,一个项目,放到服务器(tomcat)下面的跑,但第二天,总是报错,项目还不能跑 com.mysql.jdbc.exceptions.jdbc4.CommunicationsExce ...
- MySQL参数max_connect_errors分析释疑
最近一MySQL服务器,由于一些特殊因素遇到"ERROR 1129 (00000): Host 'xxx' is blocked because of many connection e ...
- MySQL程序之mysql参数详解
MySQL程序之mysql参数详解 mysql 是一个命令行客户程序,用于交互式或以批处理模式执行SQL语句 用法: mysql [OPTIONS] [database] 参数: 1.-? --hel ...
随机推荐
- Python并发式编程
目录 进程 线程 GIL(Global Interpreter Lock) 线程的调用方式 直接调用 继承调用 join&Daemon方法 Daemon(True) 同步锁 死锁 递归锁 同步 ...
- VS2019 离线安装方法详解
本文详细介绍了 VS2019 离线安装的相关步骤,以桌面开发为主下载 C++桌面开发..NET 桌面开发相关的工作负载.MFC 可选组件及帮助查看器. 工作负载(Workload) 离线安装需要先根据 ...
- Bayes factor
bayes因子为什么一定要除以先验机会比,如果是想用样本的作用,来判断支持原来的假设θ_0,H_0的力度,直接用后验概率比不就好了吗? 左边等于右边
- Java数据库学习之SQL语句动态拼接
public class UserDaoImpl implements UserDao { @Override public List<User> getUserByPage(PageIn ...
- react dnd demo
target import React ,{ Component } from 'react'; import { DropTarget } from 'react-dnd'; import Item ...
- centos7之zabbix邮件报警(短信报警)
前言 前面我们介绍了zabbix的基本linux和window及SNMP流量的简单监控,我们知道作为运维人员,需要7x24小时待命,但是我们不可能时时刻刻都坐在电脑旁边查看监控上的各个主机状态,所以我 ...
- POJ 1915 Knight Moves
POJ 1915 Knight Moves Knight Moves Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 29 ...
- CentOS_7下安装Nginx服务
安装make: yum -y install gcc automake autoconf libtool make make是一个命令工具,是一个解释makefile中指令的命令工具.它可以简化编译过 ...
- docker容器运行后退出,怎么才能一直运行?【转】
现象 启动docker容器 docker run –name [CONTAINER_NAME] [CONTAINER_ID] 查看容器运行状态 docker ps -a 发现刚刚启动的mydocker ...
- 「洛谷4197」「BZOJ3545」peak【线段树合并】
题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...