今日在查看锁超时的设置时,看到showvariableslike%timeout%;语句输出结果中的十几种超时参数时突然想整理一下,不知道大家有没有想过,这么多的timeout参数,到底有什么区别,都是做什么用的呢?
MySQL[(none)]>showvariableslike%timeout%; +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800| |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800| +------------------------------+----------+ 13rowsinset(0.00sec)
PS:文档说明
根据这些参数的global和session级别分别进行阐述
基于MySQL5.6.30编写
加载了半同步复制插件,所以才能看到半同步相关的参数
验证演示过程可能会打开两个MySQL会话进行验证,也可能只打开一个MySQL会话进行验证
只针对大家平时容易高混淆的或者说不好理解的超时参数做步骤演示,容易理解的超时参数只做文字描述,不做步骤演示
大部分参数基于MySQL命令行客户端做的演示,但wait_timeout和interactive_timeout这两个比较特殊,为了对比不同客户端的差异,还使用了python演示
a)、connect_timeout:在获取连接阶段(authenticate)起作用
获取MySQL连接是多次握手的结果,除了用户名和密码的匹配校验外,还有IP->HOST->DNS->IP验证,任何一步都可能因为网络问题导致线程阻塞。为了防止线程浪费在不必要的校验等待上,超过connect_timeout的连接请求将会被拒绝。 官方描述:connect_timeout(ThenumberofsecondsthatthemysqldserverwaitsforaconnectpacketbeforerespondingwithBadhandshake.Thedefaultvalueis10seconds)b)、interactive_timeout和wait_timeout:在连接空闲阶段(sleep)起作用
即使没有网络问题,也不能允许客户端一直占用连接。对于保持sleep状态超过了wait_timeout(或interactive_timeout,取决于client_interactive标志)的客户端,MySQL会主动断开连接。 官方描述: wait_timeout:Thenumberofsecondstheserverwaitsforactivityonanoninteractiveconnectionbeforeclosingit.Onthreadstartup,thesessionwait_timeoutvalueisinitializedfromtheglobalwait_timeoutvalueorfromtheglobalinteractive_timeoutvalue,dependingonthetypeofclient(asdefinedbytheCLIENT_INTERACTIVEconnectoptiontomysql_real_connect()). interactive_timeout:Thenumberofsecondstheserverwaitsforactivityonaninteractiveconnectionbeforeclosingit.AninteractiveclientisdefinedasaclientthatusestheCLIENT_INTERACTIVEoptiontomysql_real_connect()c)、net_read_timeout和net_write_timeout:则是在连接繁忙阶段(query)起作用。
即使连接没有处于sleep状态,即客户端忙于计算或者存储数据,MySQL也选择了有条件的等待。在数据包的分发过程中,客户端可能来不及响应(发送、接收、或者处理数据包太慢)。 为了保证连接不被浪费在无尽的等待中,MySQL也会选择有条件(net_read_timeout和net_write_timeout)地主动断开连接。 这个参数只对TCP/IP链接有效,只针对在Activity状态下的线程有效 官方描述: net_read_timeout:Thenumberofsecondstowaitformoredatafromaconnectionbeforeabortingtheread.Whentheserverisreadingfromtheclient,net_read_timeoutisthetimeoutvaluecontrollingwhentoabort.Whentheserveriswritingtotheclient,net_write_timeoutisthetimeoutvaluecontrollingwhentoabort net_write_timeout:Thenumberofsecondstowaitforablocktobewrittentoaconnectionbeforeabortingthewrite.Seealsonet_read_timeout.d)、handshake流程
在TCP三次握手的基础之上,简历MySQL通讯协议的连接,这个连接建立过程受connect_timeout参数控制
--------------------TCPestablished--------------------
MySQLServer(10.10.20.96)------->Client(10.10.20.51)
Client(10.10.20.51)------->MySQLServer(10.10.20.96)
MySQLServer(10.10.20.96)------->Client(10.10.20.51)--------------------established--------------------
在MySQL通讯协议建立连接之后,此时客户端连接的超时受wait_timeout和interactive_timeout参数控制
建立连接后无交互:MySQLserver---wait_timeout---Client
建立连接交互后:MySQLserver---interactive_timeout---Client 在如果客户端有数据包传输,那么这个数据包的传输超时由net_read_timeout和net_write_timeout参数控制
-------------------client与server端有数据传输时-------------------
client----->MySQLServer(net_read_timeout)
client<-----MySQLServer(net_write_timeout) 1.2.connect_timeout:该参数没有session级别,是一个global级别变量 ##使用mysql客户端打开一个会话,并设置全局connect_timeout=5 MySQL[(none)]>setglobalconnect_timeout=5; QueryOK,0rowsaffected(0.00sec) MySQL[(none)]> ##由于mysql客户端不是很好模拟连接阶段(authenticate)的超时,所以使用telnet来发包给mysql,因为telnet的包并不遵循mysql的通讯协议 [root@localhost~]#timetelnet127.0.0.13306 Trying127.0.0.1... Connectedto127.0.0.1. Escapecharacteris^]. N 5.6.30-logwA{k)&)S9#A`?Z&O9pJ`mysql_native_passwordConnectionclosedbyforeignhost. real 0m5.022s#这里可以看到5S之后连接断开 user 0m0.000s sys 0m0.010s ##回到mysql客户端:修改全局connect_timeout为10S MySQL[(none)]>setglobalconnect_timeout=10; QueryOK,0rowsaffected(0.00sec) MySQL[(none)]> ##使用telnet再试一次 [root@localhost~]#timetelnet127.0.0.13306 Trying127.0.0.1... Connectedto127.0.0.1. Escapecharacteris^]. N 5.6.30-loggZoA3{6:S\D}iu3;n:uafmysql_native_passwordConnectionclosedbyforeignhost. real 0m10.012s user 0m0.000s sys 0m0.002s 从上面的结果中可以看到,MySQL客户端与服务端的连接阶段(authenticate)的超时由参数connect_timeout控制。 1.3.interactive_tineout和wait_timeout参数 1.3.1.interactive_timeout:(MySQL命令行客户端) 1.3.1.1.session级别修改interactive_timeout ##打开第一个会话,设置session级别的interactive_timeout=2 MySQL[(none)]>setsessioninteractive_timeout=2; QueryOK,0rowsaffected(0.00sec) MySQL[(none)]>selectsleep(3);showsessionvariableslike%timeout%;showglobalvariableslike%timeout%; +----------+ |sleep(3)| +----------+ |0| +----------+ 1rowinset(3.00sec) +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|2|#session级别的interactive_timeout改变了 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#session级别的wait_timeout没有影响 +------------------------------+----------+ 13rowsinset(0.00sec) +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#global级别的interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#global级别的wait_timeout没有影响 +------------------------------+----------+ 13rowsinset(0.00sec) ##打开第二个会话,执行show语句 MySQL[(none)]>showsessionvariableslike%timeout%;showglobalvariableslike%timeout%; +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#session级别的interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#session级别的wait_timeout没有影响 +------------------------------+----------+ 13rowsinset(0.00sec) +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#global级别的interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#global级别的wait_timeout没有影响 +------------------------------+----------+ 13rowsinset(0.00sec) 从上面的结果可以看到,设置session级别的interactive_timeout对wait_timeout的session和global级别都没有影响 1.3.1.2.global级别修改interactive_timeout ###回到第一个会话中,设置globalinteractive_timeout=20 MySQL[(none)]>setglobalinteractive_timeout=20; QueryOK,0rowsaffected(0.00sec) MySQL[(none)]>selectsleep(3);showsessionvariableslike%timeout%;showglobalvariableslike%timeout%; +----------+ |sleep(3)| +----------+ |0| +----------+ 1rowinset(3.00sec) +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|2|#session级别的interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#session级别的wait_timeout没有影响 +------------------------------+----------+ 13rowsinset(0.00sec) +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|20|#global级别的interactive_timeout改变了 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#global级别的wait_timeout没有影响 +------------------------------+----------+ 13rowsinset(0.00sec) #第二个会话断开之后重连,再执行show语句 MySQL[(none)]>showsessionvariableslike%timeout%;showglobalvariableslike%timeout%; +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|20|#session级别的interactive_timeout改变了 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|20|#session级别的wait_timeout改变了 +------------------------------+----------+ 13rowsinset(0.00sec) +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|20|#global级别的interactive_timeout改变了 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#global级别的wait_timeout没有影响 +------------------------------+----------+ 13rowsinset(0.00sec) 从上面的结果中可以看到:如果改变了global级别的interactive_timeout值,对当前连接不生效,对后续新连接的wait_timeout的session级别生效,global级别不生效,interactive_timeout的global级别和session级别都生效 1.3.2.wait_timeout:(MySQL命令行客户端) 1.3.2.1.session级别修改wait_timeout这里为了验证后续的值不产生混乱,先把interactive_timeout的值恢复为172800并重连连接(connect_timeout默认是10,此时已经是这个值了,不用再修改),然后再修改wait_timeout
MySQL[(none)]>setglobalinteractive_timeout=172800; QueryOK,0rowsaffected(0.00sec)
MySQL[(none)]>Ctrl-C--exit! Aborted [root@localhost~]#mysql-uqogir_env-pletsg0-S/home/mysql/data/mysqldata1/sock/mysql.sock WelcometotheMariaDBmonitor.Commandsendwith;or\g. YourMySQLconnectionidis21 Serverversion:5.6.30-logMySQLCommunityServer(GPL)
Copyright(c)2000,2016,Oracle,MariaDBCorporationAbandothers.
Typehelp;or\hforhelp.Type\ctoclearthecurrentinputstatement.
MySQL[(none)]>showsessionvariableslike%timeout%;showglobalvariableslike%timeout%; +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800| |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800| +------------------------------+----------+ 13rowsinset(0.00sec)
+------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800| |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800| +------------------------------+----------+ 13rowsinset(0.00sec)
现在,开始1.3.2.小节的验证
MySQL[(none)]>setsessionwait_timeout=2; QueryOK,0rowsaffected(0.00sec)
MySQL[(none)]>selectsleep(3);showsessionvariableslike%timeout%;showglobalvariableslike%timeout%; ERROR2006(HY000):MySQLserverhasgoneaway Noconnection.Tryingtoreconnect... Connectionid:22 Currentdatabase:***NONE***#从这里可以看到,当前连接被断开并重连了
+----------+ |sleep(3)| +----------+ |0| +----------+ 1rowinset(3.00sec)
+------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#重连之后的session级别参数,interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#重连之后的session级别参数,wait_timeout恢复了172800 +------------------------------+----------+ 13rowsinset(0.01sec)
+------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#重连之后的global级别参数,interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#重连之后的global级别参数,wait_timeout恢复了172800,即新的连接不受影响 +------------------------------+----------+ 13rowsinset(0.00sec)
MySQL[(none)]>showsessionvariableslike%timeout%;showglobalvariableslike%timeout%; +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#session级别的interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#session级别的wait_timeout没有影响 +------------------------------+----------+ 13rowsinset(0.00sec)
+------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#global级别的interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#global级别的wait_timeout没有影响 +------------------------------+----------+ 13rowsinset(0.00sec)
2016-11-0719:08:243391[Warning]Abortedconnection21todb:unconnecteduser:qogir_envhost:localhost(Gottimeoutreadingcommunicationpackets)
从上面的结果中可以看到:
session级别的wait_timeout变量在连接初始化时,继承global的interactive_timeout参数值
session级别的wait_timeout对当前交互连接生效(即当前连接的超时使用的是sessionwait_timeout,sessioninteractive_timeout不生效)
有一点要注意,如果是新的连接(即断开重连的或者新的连接),session级别的wait_timeout会使用global级别的interactive_timeout值覆盖,因为interactive_timeout值是对后续新连接生效(参考1.2.2小节验证过程)
1.3.2.2.global级别修改wait_timeout #打开第一个会话,修改globalwait_timeout=2 MySQL[(none)]>setglobalwait_timeout=2; QueryOK,0rowsaffected(0.00sec) MySQL[(none)]>selectsleep(3);showsessionvariableslike%timeout%;showglobalvariableslike%timeout%; +----------+ |sleep(3)| +----------+ |0| +----------+ 1rowinset(3.00sec) +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#session级别的interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#session级别的wait_timeout没有影响 +------------------------------+----------+ 13rowsinset(0.00sec) +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#global级别的interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|2|#global级别的wait_timeout改变了 +------------------------------+----------+ 13rowsinset(0.00sec) #打开第二个会话,注意需要断开重连,再执行show语句 MySQL[(none)]>showsessionvariableslike%timeout%;showglobalvariableslike%timeout%; +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#session级别的interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|172800|#session级别的wait_timeout没有影响,因为前面说过,这里新连接的session的wait_timeout会继承globalinteractive_timeout的值 +------------------------------+----------+ 13rowsinset(0.00sec) +------------------------------+----------+ |Variable_name|Value| +------------------------------+----------+ |connect_timeout|10| |delayed_insert_timeout|300| |innodb_flush_log_at_timeout|1| |innodb_lock_wait_timeout|120| |innodb_rollback_on_timeout|ON| |interactive_timeout|172800|#global级别的interactive_timeout没有影响 |lock_wait_timeout|31536000| |net_read_timeout|30| |net_write_timeout|60| |rpl_semi_sync_master_timeout|10000| |rpl_stop_slave_timeout|31536000| |slave_net_timeout|10| |wait_timeout|2|#global级别的wait_timeout改变了 +------------------------------+----------+ 13rowsinset(0.00sec) 从上面的结果中可以看到:global级别的wait_timeout变量在初始化时,继承global的wait_timeout参数值,默认8小时 1.3.3.interactive_timeout和wait_timeout参数(pythonMySQLdriver)本小节演示的python代码如下:
#cattest_timeout.py #!/bin/envpython
importMySQLdb importsys importtime
wait_timeout=5
interactive_timeout=10
mysql_user=qbench
mysql_password=qbench
mysql_ip=10.10.30.68
rest_conn=MySQLdb.connect(user=mysql_user,passwd=mysql_password,host=mysql_ip) rest_cur=rest_conn.cursor() rest_cur.execute("showvariableslike%timeout%;") datas=rest_cur.fetchall() datas=dict(datas)
rest_wait_timeout=datas[wait_timeout] rest_interactive_timeout=datas[interactive_timeout]
rest_cur.close() rest_conn.close()
defnew_connect(info,timeout): new_conn=MySQLdb.connect(user=mysql_user,passwd=mysql_password,host=mysql_ip) new_cur=new_conn.cursor() print%s\n%s%(-*50,str(info)) #sql="selectsleep(%s);"%int(timeout+1) #print"执行sleepsql语句:%s"%str(sql) new_cur.execute("showvariableslike%timeout%;") new_datas=new_cur.fetchall() new_datas=dict(new_datas)
printwait_timeout=%s%new_datas[wait_timeout] printinteractive_timeout=%s%new_datas[interactive_timeout] print"sleep%s秒之后再次执行sql---"%int(timeout) time.sleep(int(timeout)) #new_cur.execute("%s"%str(sql)) new_cur.execute("showvariableslike%timeout%;") new_datas=new_cur.fetchall() new_datas=dict(new_datas) printwait_timeout=%s%new_datas[wait_timeout] printinteractive_timeout=%s%new_datas[interactive_timeout] new_cur.close() new_conn.close()defcurrent_connect(): curr_conn=MySQLdb.connect(user=mysql_user,passwd=mysql_password,host=mysql_ip) curr_cur=curr_conn.cursor() print"在第一个连接中修改globalwait_timeout为:%s"%wait_timeout curr_cur.execute("setglobalwait_timeout=%s;"%wait_timeout) curr_cur.execute("showvariableslike%timeout%;") curr_datas1=curr_cur.fetchall() curr_datas1=dict(curr_datas1)
print"%s\n第一个连接保持不断开的session级别的超时信息:"%(-*100) printwait_timeout=%s%curr_datas1[wait_timeout] printinteractive_timeout=%s%curr_datas1[interactive_timeout] new_connect(info=第一个连接修改globalwait_timeout为:%s之后,登录新的连接的session级别的超时信息如下:%wait_timeout,timeout=wait_timeout) restore() curr_cur.close() curr_cur=curr_conn.cursor() print"在第一个连接中修改globalinteractive_timeout为:%s"%interactive_timeout curr_cur.execute("setglobalinteractive_timeout=%s;"%interactive_timeout) curr_cur.execute("showvariableslike%timeout%;") curr_datas2=curr_cur.fetchall() curr_datas2=dict(curr_datas2) print"%s\n第一个连接保持不断开的session级别的超时信息:"%(-*100) printwait_timeout=%s%curr_datas2[wait_timeout] printinteractive_timeout=%s%curr_datas2[interactive_timeout] new_connect(info=第一个连接修改globalinteractive_timeout为:%s之后,登录新的连接的session级别的超时信息如下:%interactive_timeout,timeout=interactive_timeout) curr_cur.close() curr_conn.close()defrestore(): print"开启新的连接执行恢复参数初始设置----------------------" rest_conn=MySQLdb.connect(user=mysql_user,passwd=mysql_password,host=mysql_ip) rest_cur=rest_conn.cursor() rest_cur.execute("setglobalwait_timeout=%s,interactive_timeout=%s;"%(rest_wait_timeout,rest_interactive_timeout))
rest_cur.close() rest_conn.close()print=*100 try: current_connect() exceptException,e: printe else: restore()
print=*100
跑一下这个脚本,打印结果如下:
从上面的结果中可以看到,第一个会话中修改globalwait_timeout=5之后,新的连接上来,超过5秒没有发送新的数据包,连接就被断开。
综合1.3小节演示结果来看
MySQL命令行客户端下:global级别的interactive_timeout修改对当前连接不生效,但能影响新的连接的globainteractive_timeout、sessioninteractive_timeout、sessionwait_timeout数值
MySQL命令行客户端下:session级别的interactive_timeout的修改除了能使sessioninteractive_timeout数值改变之外没有什么作用
MySQL命令行客户端下:global级别的wait_timeout的修改除了能使globalwait_timeout数值改变之外没有什么作用
MySQL命令行客户端下:session级别的wait_timeout能改变sessionwait_timeout数值其对当前连接生效。
pythonMySQLdriver:修改globalwait_timeout对当前连接不生效,但能影响新的连接的globalwait_timeout、sessionwait_timeout
pythonMySQLdriver:修改sessionwait_timeout只对当前连接生效
pythonMySQLdriver:修改globalinteractive_timeout对当前连接不生效,能影响新的连接的globalinteractive_timeout、sessioninteractive_timeout
pythonMySQLdriver:修改sessioninteractive_timeout除了能使sessioninteractive_timeout数值改变之外没有什么作用
PS:思考?
为什么MySQL命令行客户端中新的连接的sessionwait_timeout不是使用的globalwait_timeout的值,而是使用的interactive_timeout的值?但是,为什么pythonMySQLdriver中,新的连接的sessionwait_timeout就是按照正常的逻辑使用的是globalwait_timeout的值?这里先卖个关子,问题的答案得去源码中找,参考链接:http://dev.mysql.com/doc/refman/5.6/en/mysql-real-connect.html
1.4.net_write_timeoutmysql服务端向客户端写(发送)数据时,服务端等待客户端响应的超时时间,当服务端正在写数据到客户端时,net_write_timeout控制何时超时
对于这个参数,session和global级别并没有什么特别,session级别只对当前连接生效,global级别只对新的连接生效。默认值是60S
下面使用tc命令模拟网络延迟来进行演示
tcqdiscadddeveth0rootnetemdelay1s
mysql-uqbench-pqbench-h10.10.30.68 mysql>setglobalnet_write_timeout=1; QueryOK,0rowsaffected(0.00sec)
[root@20bc83fd-1489-4b60-976b-d1823e7dc36edata]#timemysqldump-uqbench-pqbench-h10.10.30.68--single-transaction--master-data=2sbtestsbtest2>sbtest2.sql Warning:Usingapasswordonthecommandlineinterfacecanbeinsecure. mysqldump:Error2013:LostconnectiontoMySQLserverduringquerywhendumpingtablesbtest2atrow:85#从这里可以看到,不到一分钟时间,连接就被断开了
real 0m54.049s user 0m0.009s sys 0m0.011s
mysql-uqbench-pqbench-h10.10.30.68 mysql>setglobalnet_write_timeout=60; QueryOK,0rowsaffected(0.00sec)
[root@20bc83fd-1489-4b60-976b-d1823e7dc36edata]#timemysqldump-uqbench-pqbench-h10.10.30.68--single-transaction--master-data=2sbtestsbtest2>sbtest2.sql Warning:Usingapasswordonthecommandlineinterfacecanbeinsecure.
real 14m41.744s user 0m18.662s sys 0m7.886s
[root@20bc83fd-1489-4b60-976b-d1823e7dc36edata]#ls-lh total963M drwxr-xr-x12mysqlmysql137Dec3015:04mysqldata1 drwxr-xr-x2mysqlmysql6Dec3015:04recovery -rw-r--r--1rootroot963MDec3015:30sbtest2.sql#这里可以看到,消耗15分钟之后,备份成功,备份文件大小接近1G [root@20bc83fd-1489-4b60-976b-d1823e7dc36edata]#
1.5.net_read_timeoutmysql服务端从客户端读取(接收)数据时,服务端等待客户端响应的超时时间,当服务端正在从客户端读取数据时,net_read_timeout控制何时超时
对于这个参数,session和global级别并没有什么特别,session级别只对当前连接生效,global级别只对新的连接生效。默认值是30S
下面接着1.4小节进行演示,使用1.4小节中的备份结果导入数据库
Warning:Usingapasswordonthecommandlineinterfacecanbeinsecure. WelcometotheMySQLmonitor.Commandsendwith;or\g. YourMySQLconnectionidis15453 Serverversion:5.6.30-logMySQLCommunityServer(GPL)
Copyright(c)2000,2016,Oracleand/oritsaffiliates.Allrightsreserved.
OracleisaregisteredtrademarkofOracleCorporationand/orits affiliates.Othernamesmaybetrademarksoftheirrespective owners.
Typehelp;or\hforhelp.Type\ctoclearthecurrentinputstatement.
mysql>showvariableslike%net_read_timeout%; +------------------+-------+ |Variable_name|Value| +------------------+-------+ |net_read_timeout|30| +------------------+-------+ 1rowinset(0.00sec)
mysql>
[root@20bc83fd-1489-4b60-976b-d1823e7dc36edata]#timemysql-uqbench-pqbench-h10.10.30.68sbtest<sbtest2.sql Warning:Usingapasswordonthecommandlineinterfacecanbeinsecure.
real 37m17.831s#导入成功,耗时38分钟左右 user 0m22.797s sys 0m3.436s
[root@555f12f7-850d-4f42-867c-2d12890beb40data]#mysql-uqbench-pqbench-h10.10.30.68 Warning:Usingapasswordonthecommandlineinterfacecanbeinsecure. WelcometotheMySQLmonitor.Commandsendwith;or\g. YourMySQLconnectionidis17040 Serverversion:5.6.30-logMySQLCommunityServer(GPL)
Copyright(c)2000,2016,Oracleand/oritsaffiliates.Allrightsreserved.
OracleisaregisteredtrademarkofOracleCorporationand/orits affiliates.Othernamesmaybetrademarksoftheirrespective owners.
Typehelp;or\hforhelp.Type\ctoclearthecurrentinputstatement.
mysql>setglobalnet_read_timeout=1; QueryOK,0rowsaffected(0.00sec)
mysql>
tcqdiscdeldeveth0root tcqdiscadddeveth0rootnetemcorrupt20%loss10%delay2sreorder20%
timemysql-uqbench-pqbench-h10.10.30.68sbtest<sbtest2.sql
mysql>showprocesslist; +-------+--------+-------------------+--------+---------+------+-------+------------------+ |Id|User|Host|db|Command|Time|State|Info| +-------+--------+-------------------+--------+---------+------+-------+------------------+ |17129|qbench|10.10.30.78:16167|sbtest|Sleep|207||NULL| |17159|qbench|10.10.30.68:47148|NULL|Query|0|init|showprocesslist| +-------+--------+-------------------+--------+---------+------+-------+------------------+ 2rowsinset(0.00sec)
mysql>kill17129;##尝试kill掉这个连接 QueryOK,0rowsaffected(0.00sec)
mysql>showprocesslist; +-------+--------+-------------------+------+---------+------+-------+------------------+ |Id|User|Host|db|Command|Time|State|Info| +-------+--------+-------------------+------+---------+------+-------+------------------+ |17159|qbench|10.10.30.68:47148|NULL|Query|0|init|showprocesslist| +-------+--------+-------------------+------+---------+------+-------+------------------+ 1rowinset(0.00sec)
mysql>usesbtest Readingtableinformationforcompletionoftableandcolumnnames Youcanturnoffthisfeaturetogetaquickerstartupwith-A
Databasechanged mysql>selectcount()fromsbtest2;##然后再查询一下sbtest2表的数据,发现是空的 +----------+ |count()| +----------+ |0| +----------+ 1rowinset(0.00sec)
[root@20bc83fd-1489-4b60-976b-d1823e7dc36edata]#timemysql-uqbench-pqbench-h10.10.30.68sbtest<sbtest2.sql ERROR2006(HY000)atline47:MySQLserverhasgoneaway##发现断开了,囧。。
real 5m42.419s user 0m0.031s sys 0m0.017s
从上面的结果中可以看到:修改net_read_timeout=1,并在客户端导入数据到server的时候,并没有如预期的超时断开客户端连接。猜测可能是客户端导入数据到server端的时候,server端接收包超时之后没有发起kill掉客户端的操作,所以不手动执行一把kill的话,客户端一直在那里不动,而server端的连接线程也一直处于sleep状态
PS:
1.4和1.5小节演示用数据库帐号权限:SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,RELOAD,INDEX,ALTER,SUPER,LOCKTABLES,PROCESS
与net_read_timeout和net_write_timeout相关的还有一个参数,net_retry_count,官方描述如下:
Ifareadorwriteonacommunicationportisinterrupted,retrythismanytimesbeforegivingup. 2、锁类超时 2.1.innodb_lock_wait_timeout官方描述:
ThelengthoftimeinsecondsanInnoDBtransactionwaitsforarowlockbeforegivingupinnodb使用这个参数能够有效避免在资源有限的情况下产生太多的锁等待;指的是事务等待获取资源时等待的最长时间,超过这个时间还未分配到资源则会返回应用失败;参数的时间单位是秒,最小可设置为1s(一般不会设置得这么小),最大可设置1073741824秒(34年,一条语句锁等待超过30分钟估计业务该有反馈了),默认安装时这个值是50s,超过这个时间会报ERROR1205(HY000):Lockwaittimeoutexceeded;tryrestartingtransaction
MySQL[(none)]>usetest; Readingtableinformationforcompletionoftableandcolumnnames Youcanturnoffthisfeaturetogetaquickerstartupwith-A
Databasechanged MySQL[test]>createtabletest(idint); QueryOK,0rowsaffected(0.03sec)
MySQL[test]>insertintotestvalues(1); QueryOK,1rowaffected(0.01sec)
MySQL[test]>select*fromtest; +------+ |id| +------+ |1| +------+ 1rowinset(0.00sec)
MySQL[test]>setinnodb_lock_wait_timeout=1; QueryOK,0rowsaffected(0.00sec)
MySQL[test]>
MySQL[test]>usetest Databasechanged MySQL[test]>begin; QueryOK,0rowsaffected(0.00sec)
MySQL[test]>select*fromtestwhereid=1forupdate; +------+ |id| +------+ |1| +------+ 1rowinset(0.00sec)
MySQL[test]>
MySQL[test]>select*fromtestwhereid=1forupdate; ERROR1205(HY000):Lockwaittimeoutexceeded;tryrestartingtransaction MySQL[test]>
对于这个参数,session和global级别并没有什么特别,session级别只对当前连接生效,global级别只对新的连接生效
从上面的结果中可以看到,把innodb_lock_wait_timeout设置为1S之后,对于同一行的操作,锁等待超过1S就被终止事务了
PS:
测试结果是在RR隔离级别下基于innodb表的DML操作
2.2.innodb_rollback_on_timeout官方描述:
InMySQL5.6,InnoDBrollsbackonlythelaststatementonatransactiontimeoutbydefault.If--innodb_rollback_on_timeoutisspecified,atransactiontimeoutcausesInnoDBtoabortandrollbacktheentiretransaction默认情况下innodb_lock_wait_timeout超时后只是超时的sql执行失败,整个事务并不回滚,也不做提交,如需要事务在超时的时候回滚,则需要设置innodb_rollback_on_timeout=ON,该参数默认为OFF
MySQL[test]>showvariableslike%rollback%; +----------------------------+-------+ |Variable_name|Value| +----------------------------+-------+ |innodb_rollback_on_timeout|OFF| |innodb_rollback_segments|128| +----------------------------+-------+ 2rowsinset(0.00sec)
MySQL[test]>usetest Databasechanged MySQL[test]>showtables; Emptyset(0.00sec)
MySQL[test]>createtabletest(idint); QueryOK,0rowsaffected(0.05sec)
MySQL[test]>begin; QueryOK,0rowsaffected(0.00sec)
MySQL[test]>insertintotest(id)values(1),(2),(3),(4); QueryOK,1rowaffected(0.00sec)
MySQL[test]>select*fromtest; +------+ |id| +------+ |1| |2| |3| |4| +------+ 4rowsinset(0.00sec)
MySQL[(none)]>usetest Readingtableinformationforcompletionoftableandcolumnnames Youcanturnoffthisfeaturetogetaquickerstartupwith-A MySQL[(none)]>begin; QueryOK,0rowsaffected(0.00sec)
MySQL[test]>insertintotestvalues(5); QueryOK,1rowaffected(0.00sec)
MySQL[test]>select*fromtest; +------+ |id| +------+ |5| +------+ 2rowsinset(0.00sec)
MySQL[test]>updatetestsetid=6whereid=5;#因为第二个会话插入第=5这行数据时,对5及其以后的范围加了锁,也没有提交,所以这个这里的操作需要进行锁等待 ERROR1205(HY000):Lockwaittimeoutexceeded;tryrestartingtransaction MySQL[test]>select*fromtest;#这里可以看到,超时之后,第一个会话最开始在显式事务中插入的几行数据并没有回滚 +------+ |id| +------+ |1| |2| |3| |4| +------+ 4rowsinset(0.00sec)
##此时,你需要自行决定会话1中插入的数据是要提交,还是需要回滚,当然,如果断开连接,事务会自动回滚,为了方便后续的测试,先在两个会话中都做rollback操作
从上面的结果中可以看到,默认情况下innodb_rollback_on_timeout为OFF,此时超时终止的会话中的事务DML修改的数据不会自动回滚。
现在,把innodb_rollback_on_timeout参数在my.cnf中加入并改为ON,重启mysql,再次插入相同数据试试看
MySQL[test]>showvariableslike%rollback%; +----------------------------+-------+ |Variable_name|Value| +----------------------------+-------+ |innodb_rollback_on_timeout|ON| |innodb_rollback_segments|128| +----------------------------+-------+ 2rowsinset(0.00sec)
MySQL[test]>usetest Databasechanged
MySQL[test]>begin; QueryOK,0rowsaffected(0.00sec)
MySQL[test]>insertintotest(id)values(1),(2),(3),(4); QueryOK,1rowaffected(0.00sec)
MySQL[test]>select*fromtest; +------+ |id| +------+ |1| |2| |3| |4| +------+ 4rowsinset(0.00sec)
MySQL[(none)]>usetest Readingtableinformationforcompletionoftableandcolumnnames Youcanturnoffthisfeaturetogetaquickerstartupwith-A MySQL[(none)]>begin; QueryOK,0rowsaffected(0.00sec)
MySQL[test]>insertintotestvalues(5); QueryOK,1rowaffected(0.00sec)
MySQL[test]>select*fromtest; +------+ |id| +------+ |5| +------+ 2rowsinset(0.00sec)
MySQL[test]>updatetestsetid=6whereid=5;#因为第二个会话插入第=5这行数据时,对5及其以后的范围加了锁,也没有提交,所以这个这里的操作需要进行锁等待 ERROR1205(HY000):Lockwaittimeoutexceeded;tryrestartingtransaction MySQL[test]>select*fromtest;#这里可以看到,超时之后,第一个会话最开始在显式事务中插入的几行数据已经回滚 Emptyset(0.00sec)
从上面的结果中可以看到,把参数innodb_rollback_on_timeout设置为ON之后(注意,这个变量是只读变量,需要添加到my.cnf中并重启mysql),如果一个事务发生锁等待超时,那么这个事务没有提交的数据都会被回滚掉。
2.3.lock_wait_timeout官方描述:
Thisvariablespecifiesthetimeoutinsecondsforattemptstoacquiremetadatalocks.这里不得不提一下2.1小节的innodb_lock_wait_timeout超时参数,相信有不少人是没有搞太清楚这两者的区别,从字面上来看,前者是innodb的dml操作的行级锁的等待时间后面是获取MDL锁的等待时间,默认值是31536000秒=1年。那么,下面来演示一把吧
MySQL[test]>begin; QueryOK,0rowsaffected(0.00sec)
MySQL[test]>select*fromtestforupdate; +------+ |id| +------+ |1| |2| |3| |4| |5| +------+ 5rowsinset(0.00sec)
MySQL[test]>setlock_wait_timeout=5; QueryOK,0rowsaffected(0.00sec)
MySQL[test]>usetest Databasechanged
MySQL[test]>altertabletestaddcolumntestvarchar(100);#DDL语句执行被阻塞,5秒之后超时终止 ERROR1205(HY000):Lockwaittimeoutexceeded;tryrestartingtransaction MySQL[test]>
从上面的结果中可以看到,DDL语句的超时时间是受lock_wait_timeout参数控制的
PS:注意,凡是需要获取MDL锁的操作都受到这个超时参数的影响,不单单是DDL语句,包含在表上的DML、DDL操作,以及视图、存储过程、存储函数、locktable,flushtablewithreadlock语句等。但不适用于隐式访问系统表的语句,如:grant和revoke等
3、复制类超时 3.1.delayed_insert_timeout 官方描述:
HowmanysecondsanINSERTDELAYEDhandlerthreadshouldwaitforINSERTstatementsbeforeterminating. 为MyISAMINSERTDELAY设计的超时参数,表示INSERTDELAYhandler线程在INSERTDELAY语句终止前等待这个INSERT语句的时间,注意是表示insertdelay延迟插入的超时时间,不是insert语句。默认值是300S,从5.6.7开始被弃用(因为delayedinsert功能被弃用)后续版本将移除。 3.2.rpl_semi_sync_master_timeout 官方描述:
Avalueinmillisecondsthatcontrolshowlongthemasterwaitsonacommitforacknowledgmentfromaslavebeforetimingoutandrevertingtoasynchronousreplication.Thedefaultvalueis10000(10seconds).Thisvariableisavailableonlyifthemaster-sidesemisynchronousreplicationpluginisinstalled.
为semi-sync复制时,主库在某次事务提交时,如果等待超过rpl_semi_sync_master_timeout多秒之后仍然没有接收到任何从库做回包响应,那么主库自动降级为异步复制模式,当主库探测到有备库恢复回包时,主库自动恢复到semi-sync复制模式。默认值为10000毫秒=10秒 3.3.rpl_stop_slave_timeout 官方描述:
InMySQL5.6.13andlater,youcancontrolthelengthoftime(inseconds)thatSTOPSLAVEwaitsbeforetimingoutbysettingthisvariable.ThiscanbeusedtoavoiddeadlocksbetweenSTOPSLAVEandotherslaveSQLstatementsusingdifferentclientconnectionstotheslave.Themaximumanddefaultvalueofrpl_stop_slave_timeoutis31536000seconds(1year).Theminimumis2seconds. 5.6.13之后引入的参数,控制stopslave的执行时间,在重放一个大的事务的时候,突然执行stopslave,命令stopslave会执行很久,这个时候可能产生死锁或阻塞,严重影响性能,可以通过rpl_stop_slave_timeout参数控制stopslave的执行时间。默认值是31536000秒=1年 3.4.slave_net_timeout 官方描述:
Thenumberofsecondstowaitformoredatafromamaster/slaveconnectionbeforeabortingtheread. Slave判断主库是否挂掉的超时设置,在设定时间内依然没有获取到Master的回应就认为Master已经挂掉了,后续根据超时重连参数设置进行重连主库的操作。默认值:3600S 4、IO类超时 4.1.innodb_flush_log_at_timeout 官方描述:
WriteandflushthelogseveryNseconds.innodb_flush_log_at_timeoutwasintroducedinMySQL5.6.6.Itallowsthetimeoutperiodbetweenflushestobeincreasedinordertoreduceflushingandavoidimpactingperformanceofbinaryloggroupcommit.PriortoMySQL5.6.6,flushingfrequencywasoncepersecond.Thedefaultsettingforinnodb_flush_log_at_timeoutisalsooncepersecond. 5.6.6引入,参数innodb_flush_log_at_trx_commit=1时,此超时参数不起作用,当innodb_flush_log_at_trx_commit=0/2时才起作用。5.6.6之后表示每innodb_flush_log_at_timeout秒一次的频率刷新redolog(在5.6.6之前是固定每秒一次刷新redolog,5.6.6之后刷新频率可以通过这个参数设置,当然,这个参数本身默认值也是1S)。本文内容总结:MySQL各种超时参数的含义,1、连接、网络类超时,
原文链接:https://www.cnblogs.com/xiaoboluo768/p/6222862.html