首页 > 数据库 >MySQL空闲会话超时之interactive_timeout 与wait_timeout

MySQL空闲会话超时之interactive_timeout 与wait_timeout

时间:2024-07-25 17:52:33浏览次数:23  
标签:global 192.168 session timeout MySQL wait interactive

背景描述

在用MySQL Client链接MySQL Server进行操作的是偶,如果一段时间没有操作,可能会遇到以下错误:

ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...

或者

ERROR 2013 (HY000): Lost connection to MySQL server during query

这个报错意味着当前的链接已经断开,需要重新建立链接。 那么这个超时的时长是跟哪些有关呢?

其实,这个超时时间跟interactive_timeout、wait_timeout 的设置有关。

定义

先来看看这两个参数的含义
说明:我这里查的是MySQL 5.7版本的官方文档。https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_wait_timeout

  • wait_timeout
    • Default Value: 28800
    • The number of seconds the server waits for activity on a noninteractive connection before closing it.
      从字面上理解的话,就是服务器在非交互链接之前等待活动的秒数。
  • interactive_timeout
    • Default Value: 28800
    • The number of seconds the server waits for activity on an interactive connection before closing it.
      从字面上理解,就是服务器在交互链接之前等待活动的秒数。

看起来就是
(1)wait_timeout 针对非交互连接
(2)interactive_timeout 针对交互连接

测试

(1)只修改interactive_timeout值,观察交互式以及非交互的表现

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

mysql> SELECT @@global.wait_timeout, @@session.wait_timeout, @@global.interactive_timeout, @@session.interactive_timeout;
+-----------------------+------------------------+------------------------------+-------------------------------+
| @@global.wait_timeout | @@session.wait_timeout | @@global.interactive_timeout | @@session.interactive_timeout |
+-----------------------+------------------------+------------------------------+-------------------------------+
|                  3600 |                  28800 |                           10 |                         28800 |
+-----------------------+------------------------+------------------------------+-------------------------------+
1 row in set (0.00 sec)
  • 交互式
    Client开启一个新的链接.
MySQL [(none)]>  SELECT @@global.wait_timeout, @@session.wait_timeout, @@global.interactive_timeout, @@session.interactive_timeout;
+-----------------------+------------------------+------------------------------+-------------------------------+
| @@global.wait_timeout | @@session.wait_timeout | @@global.interactive_timeout | @@session.interactive_timeout |
+-----------------------+------------------------+------------------------------+-------------------------------+
|                  3600 |                     10 |                           10 |                            10 |
+-----------------------+------------------------+------------------------------+-------------------------------+
1 row in set (0.03 sec)

MySQL [(none)]>  SELECT @@global.wait_timeout, @@session.wait_timeout, @@global.interactive_timeout, @@session.interactive_timeout;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    10
Current database: *** NONE ***

+-----------------------+------------------------+------------------------------+-------------------------------+
| @@global.wait_timeout | @@session.wait_timeout | @@global.interactive_timeout | @@session.interactive_timeout |
+-----------------------+------------------------+------------------------------+-------------------------------+
|                  3600 |                     10 |                           10 |                            10 |
+-----------------------+------------------------+------------------------------+-------------------------------+
1 row in set (0.13 sec)

MySQL [(none)]> 

可见,当前会话的interactive_timeout=10,并且超过10s后,服务器断开了会话连接。

  • 非交互式
def main():
    num = 0 
    while True:
        max_num = session.query(func.max(JenkinsResponeTime.id)).first()
        logger.info(f'max_num:{max_num}')
        print(f'num:{num}')
        session.commit()
        num += 1
        time.sleep(15)

这里用一个python demo 去测试。

# python3 01.py 
num:0
num:1
num:2
num:3
num:4
num:5
num:6
....

可见, interactive_timeout并不影响非交互式的应用。

(2)只修改wait_timeout值,观察交互式以及非交互的表现
MySQL Server端用root@localhost 登录修改

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

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

mysql> SELECT @@global.wait_timeout, @@session.wait_timeout, @@global.interactive_timeout, @@session.interactive_timeout;
+-----------------------+------------------------+------------------------------+-------------------------------+
| @@global.wait_timeout | @@session.wait_timeout | @@global.interactive_timeout | @@session.interactive_timeout |
+-----------------------+------------------------+------------------------------+-------------------------------+
|                    10 |                  28800 |                           30 |                         28800 |
+-----------------------+------------------------+------------------------------+-------------------------------+
1 row in set (0.00 sec)

mysql> 
  • 交互式
    Client端用mysql命令登录db
MySQL [(none)]>  SELECT @@global.wait_timeout, @@session.wait_timeout, @@global.interactive_timeout, @@session.interactive_timeout;
+-----------------------+------------------------+------------------------------+-------------------------------+
| @@global.wait_timeout | @@session.wait_timeout | @@global.interactive_timeout | @@session.interactive_timeout |
+-----------------------+------------------------+------------------------------+-------------------------------+
|                    10 |                     30 |                           30 |                            30 |
+-----------------------+------------------------+------------------------------+-------------------------------+
1 row in set (0.03 sec)

MySQL [(none)]> 

可以看到,@@session.wait_timeout 不是等于global.wait_timeout, 而是等于@@global.interactive_timeout。 注意:但是这并不代表非交互的@@session.wait_timeout 等于global.wait_timeout

MySQL [(none)]>  SELECT @@global.wait_timeout, @@session.wait_timeout, @@global.interactive_timeout, @@session.interactive_timeout, now();    
+-----------------------+------------------------+------------------------------+-------------------------------+---------------------+
| @@global.wait_timeout | @@session.wait_timeout | @@global.interactive_timeout | @@session.interactive_timeout | now()               |
+-----------------------+------------------------+------------------------------+-------------------------------+---------------------+
|                    10 |                     30 |                           30 |                            30 | 2024-07-25 15:48:34 |
+-----------------------+------------------------+------------------------------+-------------------------------+---------------------+
1 row in set (0.04 sec)

MySQL [(none)]>  SELECT @@global.wait_timeout, @@session.wait_timeout, @@global.interactive_timeout, @@session.interactive_timeout, now();
+-----------------------+------------------------+------------------------------+-------------------------------+---------------------+
| @@global.wait_timeout | @@session.wait_timeout | @@global.interactive_timeout | @@session.interactive_timeout | now()               |
+-----------------------+------------------------+------------------------------+-------------------------------+---------------------+
|                    10 |                     30 |                           30 |                            30 | 2024-07-25 15:48:58 |
+-----------------------+------------------------+------------------------------+-------------------------------+---------------------+
1 row in set (0.03 sec)

MySQL [(none)]>  SELECT @@global.wait_timeout, @@session.wait_timeout, @@global.interactive_timeout, @@session.interactive_timeout, now();
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    34
Current database: *** NONE ***

+-----------------------+------------------------+------------------------------+-------------------------------+---------------------+
| @@global.wait_timeout | @@session.wait_timeout | @@global.interactive_timeout | @@session.interactive_timeout | now()               |
+-----------------------+------------------------+------------------------------+-------------------------------+---------------------+
|                    10 |                     30 |                           30 |                            30 | 2024-07-25 15:50:39 |
+-----------------------+------------------------+------------------------------+-------------------------------+---------------------+
1 row in set (0.13 sec)

MySQL [(none)]> 

并且,经过了interactive_timeout空闲后,超时断开。

  • 非交互
    python demo
while True:
    try:
        sql = "SELECT @@global.wait_timeout, @@session.wait_timeout, @@global.interactive_timeout, @@session.interactive_timeout, now();"
        result = connect.execute(sql).fetchall()
        print(result)
    except Exception as e:
        print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + f' catch exception:{e} ')
    time.sleep(15)

输出如下:

# python3 03.py 
[(10, 10, 30, 30, datetime.datetime(2024, 7, 25, 16, 14, 13))]
2024-07-25 16:14:28catch exception:(pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query')
[SQL: SELECT @@global.wait_timeout, @@session.wait_timeout, @@global.interactive_timeout, @@session.interactive_timeout, now();]
(Background on this error at: https://sqlalche.me/e/14/e3q8) 

可以看到,非交互中session.wait_timeout并不等于interactive_timeout
非交互式经过session.wait_timeout后超时。

总结

(1)交互式: 关注interactive_timeout参数。
(2)非交互式: 关注 wait_timeout参数。

延伸

我们知道Linux上有关于TCP KEEPALIVE 的一些参数, 比如tcp_keepalive_time
tcp_keepalive_time 默认值720,(2小时),就是空闲多久,开始发keepalive探测包。 那么这个是否可以会影响mysql上的超时时间呢?
这里用非交互式的做讨论。

比如wait_timeout=20 ,Client A应用 每隔30s才查询一次, Client的tcp_keepalive_time设置为15, 那么20s后,A应用是否会超时异常呢?

答案是肯定的,操作系统的tcp_keepalive_time只是一个四层的ACK空包,mysql并不鸟它。
测试如下:

# echo 15 > /proc/sys/net/ipv4/tcp_keepalive_time

16:26:22 启动应用, 可以看到在16:26:37操作系统发keepalive包, 16:26:42 超时断开。抓包如下:

16:26:22.181299 IP 192.168.0.200.39574 > 192.168.0.100.3306: Flags [P.], seq 438:451, ack 696, win 5, length 13
16:26:22.214075 IP 192.168.0.100.3306 > 192.168.0.200.39574: Flags [P.], seq 696:707, ack 451, win 237, length 11
16:26:22.253305 IP 192.168.0.200.39574 > 192.168.0.100.3306: Flags [.], ack 707, win 5, length 0


16:26:37.214296 IP 192.168.0.200.39574 > 192.168.0.100.3306: Flags [.], ack 707, win 5, length 0
16:26:37.246975 IP 192.168.0.100.3306 > 192.168.0.200.39574: Flags [.], ack 451, win 237, length 0
16:26:42.234322 IP 192.168.0.100.3306 > 192.168.0.200.39574: Flags [F.], seq 707, ack 451, win 237, length 0
16:26:42.274277 IP 192.168.0.200.39574 > 192.168.0.100.3306: Flags [.], ack 708, win 5, length 0
16:26:52.240972 IP 192.168.0.200.39574 > 192.168.0.100.3306: Flags [P.], seq 451:537, ack 708, win 5, length 86
16:26:52.241067 IP 192.168.0.200.39574 > 192.168.0.100.3306: Flags [F.], seq 537, ack 708, win 5, length 0
16:26:52.273747 IP 192.168.0.100.3306 > 192.168.0.200.39574: Flags [R], seq 2919111959, win 0, length 0
16:26:52.273787 IP 192.168.0.100.3306 > 192.168.0.200.39574: Flags [R], seq 2919111959, win 0, length 0

标签:global,192.168,session,timeout,MySQL,wait,interactive
From: https://www.cnblogs.com/doctormo/p/18323820

相关文章

  • 最新nacos下载安装,版本号2.4.0,nacos持久化存储到本地mysql中,nacos配置登录账户密码
    官网:https://nacos.io/zh-cn/docs/quickstart/quick-start1.下载地址:https://github.com/alibaba/nacos/releases网络不好,很难下载。直接使用git克隆,然后自己编译,这是最快的了。克隆:gitclonehttps://github.com/alibaba/nacos.git然后到根目录中(我的:E:\Demos\nacos),执行cmd命令:mv......
  • 虚拟机环境下Rocky 9.4安装Mysql8并配置Dbeaver客户端
    环境:服务器操作系统:Rocky9.4数据库:mysql8.0.38客户端操作系统:windows10Dbeaver版本:24.1.3Rocky9.4安装镜像下载地址:https://mirrors.aliyun.com/rockylinux/9.4/isos/x86_64/Rocky-9.4-x86_64-dvd.isoDbeaver安装文件下载链接:https://dbeaver.io/files/dbeaver-c......
  • MySQL 学习笔记 进阶(存储引擎,索引上)
    存储引擎 存储引擎-MySQL体系结构连接层服务层引擎层存储层 存储引擎-简介简介:存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,所以存储引擎也可被成为表类型。在创建表时,指定存储引擎CREATETABLE表名(......
  • 第九讲: MySQL为什么有时候会选错索引?
    第九讲:MySQL为什么有时候会选错索引?​ 前面我们介绍过索引,你已经知道了在MySQL中一张表其实是可以支持多个索引的。​ 但是,你写SQL语句的时候,并没有主动指定使用哪个索引。也就是说,使用哪个索引是由MySQL来确定的。不知道你有没有碰到过这种情况,一条本来可以执行得很快......
  • MySQL篇
    一、定位慢查询定位慢查询很简单,主要有以下方式:通过运维工具分析开启mysql慢日志在mysql的配置文件/etc/my.cnf中配置并开启慢日志功能#开启MySQL慢日志查询开关slow_query_log=1#设置慢日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志long_quer......
  • mysql常用语法
    MySQL约束注释--单行注释/*多行注释*/#井号注释MySQL命令执行顺序FROM>ON>JOINWHERE>GROUPBY>HAVING+聚合函数>SELECT>ORDERBY>LIMIT数据库设计——DDLshowdatabases; --查看当前所有的数据库use[数据库名]; --打开指定的数据库showtab......
  • Mysql常用函数
    1、FIND_IN_SETFIND_IN_SET()是一个MySQL中的字符串函数,用于在一个由逗号分隔的字符串列表中查找指定字符串的位置。如果找到了指定的字符串,FIND_IN_SET()将返回该字符串在列表中的位置(索引值)。如果没有找到,它将返回0。其语法如下:FIND_IN_SET(str,strlist)str:......
  • Mysql 函数 (进阶介绍 八)
    目录MySQLCURTIME()函数定义和用法语法实例MySQLDATE()函数定义和用法语法实例MySQLEXTRACT()函数定义和用法语法实例MySQL字符串连接CONCAT()函数使用方法:MySQL字符串截取SUBSTRING()函数 使用方法:MySQL数学函数使用方法:mysqlsubstr()函数截......
  • 一文了解MySQL索引机制
    接触MySQL数据库的小伙伴一定避不开索引,索引的出现是为了提高数据查询的效率,就像书的目录一样。某一个SQL查询比较慢,你第一时间想到的就是“给某个字段加个索引吧”,那么索引是什么?是如何工作的呢?一起静下心来,耐心看完这篇文章吧,干货不啰嗦,相信你一定会有所收获。一、索引模型模......
  • Mysql中修改新创建用户的密码
    创建新用户时,新用户没有权限,所以自己无法修改成简单的密码(1)可以通过root用户给权限,让新用户自己修改:1.先进入root用户,mysql-uroot-p1234562.给新用户权限:grantallprivilegeson.to'新用户名'@'localhost'withgrantoption;(其中withgrantoption是让新用户......