问题描述

最近在查看我们游戏服务器的日志时发现每过一段时间,驱动都会报如下的错误日志:

packets.go:124: write unix @->/var/run/mysqld/mysqld.sock: write: broken pipe

环境

  • mysql驱动: github.com/go-sql-driver/mysql (git SHA: be22b30)
  • Go version: go1.9 darwin/amd64
  • mysql version: Ver 5.7.19
  • Server OS: Ubuntu 17.04

过程

然后开始查资料,找到了这个链接](https://github.com/go-sql-driver/mysql/issues/446)。) 。
大意就是,mysql有个wait_timeout变量,如果一个链接在这个这个变量设置的时间段内都是空闲的,那么mysql会主动断开这个连接。但是我们是使用的这个mysql驱动无法移除database/sql.DB连接池中已经无效的连接,导致客户端(我们的服务器)这边再次使用这个已经被断开的连接的时候就会报错。

查询数据库获得如下结果:

查询

解决办法

将MaxLifetime值设置为wait_timeout的一半即可:db.SetConnMaxLifetime(time.Second * 14400)

又出问题了

但是这样只能处理时间正常流逝的情况,为了手动改时间不出这种问题,我们决定每次改时间后将mysql也一同重启。但是由此又引出了新的问题。在我们的服务器重启运行半分钟左右(期间会有数据库查询等操作),发现日志里面多了Invalid connection的错误,使用netstat -an | grep 3306查看发现了大量close_wait状态的连接。
这种情况显而易见,肯定是mysql将我们服务器的连接断开了,猜测应该和前面的情况一致,是由于连接空闲导致的。但是这并不合理,根据查询结果,我们mysql的wait_timeout变量值为28800,也就是说至少得空闲8个小时mysql才会主动断开连接,现在这点时间完全没有那么久。

继续查资料、分析

接着又是各种查资料,各种分析,最后在mysql的配置文件中发现,我们配置了wait_timeout=30。看来问题就出在这里了,空闲30秒后mysql就主动断开了连接,与实际情况相符合。那为什么我们使用show variables like '%timeout%';查询的结果是28800呢。原来使用命令查询得到的wait_timeout的值取决于interactive_timeout。虽然wait_timeout实际上是生效的,但是我们看到的,都是interactive_timeout的值。

更多

根据这个链接的描述,使用终端登录mysql进行连接时,mysql空闲断开取决于interactive_timeout,而我们使用非终端的形式连接时,mysql空闲断开取决于wait_timeout。[toc]

文章来源于互联网:服务器与mysql的连接出现大量close_wait

发表评论