背景:
golang的mysql库采用的是驱动模型
Go官方提供了database/sql
包来给用户进行和数据库打交道的工作,database/sql
库实际只提供了一套操作数据库的接口和规范,例如抽象好的SQL预处理(prepare),连接池管理,数据绑定,事务,错误处理等等。官方并没有提供具体某种数据库实现的协议支持。
和具体的数据库,例如MySQL打交道,还需要再引入MySQL的驱动
具体的底层实现库,采用“注册驱动”的方式注册到上层去使用,比如 https://github.com/go-sql-driver/mysql 这样可以降低耦合
问题与排查:
之前一直用的go-sql-driver一直都是好的,一次偶然的机会需要批量导数据,发现一些连接池长连接机制无效的问题,追踪排查了好几天。(#^.^#),也由此产生了此文
golang 版本:go 1.10.4
数据库参数配置
|
然后导数据的并发设置的是300,按照道理来说 应该是一直维持300左右的长连接的,
但是实际情况是创建了一个连接,用完之后,并没有放到连接池等待下一次使用,而是直接关闭了,于是产生了大量的短连接,参考下图11点之前的曲线,这种情况是不合理的,很奇怪~
但是只有这个服务有问题,线上很多其他的服务连接池的表现都是正常的
我起初以为是database/sql 包里面连接池的问题,一直在找其中的源码,甚至找了go不同版本(1.10和1.11)之间的差异,发现改动不大,源码中也没有看到存在什么明显的问题
在我一度怀疑人生的时候,抱着试试看的方法,把之前正常的服务用的 mysql相关依赖包全部copy了一份到新的服务的vendor里面(其中就包括go-sql-driver),试了一下,竟然正常了~~~
立马看到了曙光,试着把所有包的发布版本切换一下,试了一下,
发现go-sql-driver的v1.3.0是ok的,但是新版v1.4.0和v1.4.1 是不行的,O(∩_∩)O哈哈~
大家可以看到上图11.20之后的曲线,都是正常的,符合预期的(当时与数据库建立的长连接就是300个左右,图中看到的将近350,是因为其它进程占用了)
那接下来就是go-sql-driver v1.3.0和v1.4.0之间的差异比较了,简单比较了下,不是必现,只有在并发量越高的时候,短连接越多,也不影响mysql数据的正常使用
由于时间限制,两个版本的源码只是简单比较了一下,还未深究,暂时还未发现具体的原因
这个还需接下来细细定位下源码~~
未完待续
已经在github提了 issue了:https://github.com/go-sql-driver/mysql/issues/991
欢迎沟通,如果您已经找到原因了,可以告诉我,感激不尽~~