2014-11-28 wcdj
摘要:后台服务通常与MySQL交互使用长连接的方式,若会话超过默认8小时空闲则MySQL会对当前连接进行关闭,客户端此时再用此连接请求时就会返回2006:MySQLserver has gone away的错误提示,此类错误在某些场景下会影响用户体验,本文总结如何测试和优化此问题。
首先登录到MySQL查看设置会话超时的wait_timeout环境变量的数值。
mysql> show global variables like"%timeout%";
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| connect_timeout | 5 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| table_lock_wait_timeout | 50 |
| wait_timeout | 28800 |
+----------------------------+-------+
可见在没有心跳时MySQL主动断开的时间默认是8小时。
模拟客户端2006错误频发的场景,修改环境变量wait_timeout,可以选择以下方法中的一种来修改环境变量。
1. 在命令行上使用选项(-O wait_timeout=30)
2. 使用选项文件(优点:不需要每次运行程序时从命令行输入)
3. 用环境变量指定选项(set global wait_timeout=30;)
注意;命令行参数的优先级高于配置文件的优先级。
为了测试方便使用方法3,直接修改全局环境变量:
mysql> set global wait_timeout=30;
Query OK, 0 rows affected (0.00 sec)
mysql> show global variables like"%timeout%";
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| connect_timeout | 5 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| table_lock_wait_timeout | 50 |
| wait_timeout | 30 |
+----------------------------+-------+
10 rows in set (0.00 sec)
修改wait_timeout后,可以验证在进行一笔请求交互后,MySQL会在connection达到配置的超时后主动close连接。
14:24:51.661203 IP 10.130.145.230.mysql> 172.27.35.35.42122: Flags [F.], seq 3165, ack 614, win 1724, options[nop,nop,TS val 1971514012 ecr 1071197207], length 0
0x0000: 4508 0034 342b 4000 3c069eea 0a82 91e6 E..44+@.<.......
0x0010: ac1b 2323 0cea a48a 946aef57 9714 794f ..##.....j.W..yO
0x0020: 8011 06bc f2ae 0000 0101080a 7582 ea9c ............u...
0x0030: 3fd9 2c17 ?.,.
14:24:51.700973 IP 172.27.35.35.42122 >10.130.145.230.mysql: Flags [.], ack 3166, win 91, options [nop,nop,TS val1071202262 ecr 1971514012], length 0
0x0000: 4508 0034 5aeb 4000 4006742a ac1b 2323 E..4Z.@[email protected]*..##
0x0010: 0a82 91e6 a48a 0cea 9714794f 946a ef58 ..........yO.j.X
0x0020: 8010 005b e550 0000 0101080a 3fd9 3fd6 ...[.P......?.?.
0x0030: 7582 ea9c u...
后台服务在与MySQL建立连接完成后,可以采用定时器的方式周期地向MySQL上报心跳以防止连接被MySQL主动关闭。
void Timer::report()
{
time_t tNow = time(NULL);
if(tNow - DB_HEARTBEAT_INTERVAL_TIME >= m_tLastPingTime)
{
m_tLastPingTime = tNow;
db.ping();
}
return;
}