mysql invalid connection 错误
mysql invalid connection 错误 最近团队有同学遇到了 mysql 会偶发"invalid connection" 错误,在之前从没遇到过,因此稍微调查一下。
原因 查看 github.com/go-sql-driver/mysql@1.6.0 的源码可以看出来会返回这个错误的地方不是很多,大致可以归类以下几个case:
TCP连接已关闭:这里的连接关闭是指被动关闭,通常对数据库的连接池都由 go 的 sql 包来管理,无论是 MaxIdleTime, MaxLifetime 都是它来管理生命周期,如果取出了已过期的连接,它会重新再去取,然后关闭掉已过期的连接,这是主动关闭,源码参考 sql。被动的关闭,指从server端发起的,比如连接空闲时间 > wait_timeout,再比如 mysql or mysql proxy重启或者故障,这些都导致 invalid connection。从代码来看,导致这个错误的另一种情况是对一个已经关闭的mysqlConn 进行操作,这个case我想不到什么情况下会出现,因为逻辑上来说当这个对象被调用 Close 后,将没有机会被调用,不知道要什么情况会被复用到。 读写异常: 查看 readPacket 和 writePacket 代码可以发现,如果在读写过程发生错误,且 client 端没有 cancel context,那么会返回 invalid connection,具体的原因可以在标准输出里查看,mysql会输出 [mysql] 前缀的日志,最常见的是读写超时。 当开启插值参数后,并发使用连接:正常 mysql driver走的 prepare + exec 的过程,会产生多一次的 rtt,有些情况我们可以通过dsn参数 interpolateParams=true 来开启插值(占位符替换),而减少一次rtt。但是插值的过程会使用 conn 上的buffer,如果并发访问导致 buffer 繁忙则会返回该错误。那么什么时候会在并发下使用同一条连接呢?答案是你当你使用了一些 session性质的功能,比如 transaction or user-level lock。 插值相关的参考资料:database/sql 一点深入理解