commands out of sync. Did you run multiple statements at once?
Go 的 mysql 驱动库 github.com/go-sql-driver/mysql 在连接数据库时,有时会产生一个奇怪的错误
1 |
|
这个错误的字面意思是同一时刻执行了多个 SQL 语句。咋看上会让人感到很迷惑,特别是这个错误有可能发生在数据建立连接时。
例如下面这段代码也会遇到相同的错误信息:
1 |
|
在上面这段代码中,我们只是建立连接,还没有执行语句就发生了错误。说明错误产生的原因并不是像错误本身信息描述的那样。
为了了解这个错误产生的原因,我们打开它的源码,查找错误出现的原因。首先使用 rg
命令从代码中搜索这段文本
1 |
|
根据返回的结果,可以看到这是一个在 errors.go 中预定义好的错误。
找到这个错误之后,我们来看下这个错误是在哪被使用的。继续查找 ErrPktSyncMul
这个关键字,发现是在 packets.go 中使用的, 代码如下:
1 |
|
在这个方法中, 客户端从网络连接中读取了 mysql 服务返回的数据包,发现数据包头的 sync 信息与已经读取的 sequence 不相等,并且大于当前 sequence 的,于是认为产生了多语句执行。
但是,我们的情况并不是执行语句,而是在一开始建立连接就失败了,继续查看源码,发现在 Open 的时候,驱动会与数据库握手,同时调用 readPacket 从连接中读取数据包。
猜测是与服务端通信出现了问题,搜索相关的 issue,发现了和我们情况类似的问题 issue #1038。根据 issue 所描述,当 mariadb 服务端拒绝与当前客户端通信时就会出现这个错误。而根据下面的评论,这个错误有可能会因为特定的 mariadb 版本引发,因为 mysql 的服务端实现有 bug。mariadb 的开发者,在评论中回答道问题已经修复了。
到这里,我们终于弄清了这个错误出现的原因,并不是由于我们执行了多行语句,而是因为我们与服务端的通信被拒绝了,错误信息迷惑了我们。
因此,当连接 mysql 时出现了这个错误,可以按照下面的方式去排查
- 查看 mysql 的服务版本是不是存在 bug 的版本,如果是的,那么就需要升级服务版本
- 查看 mysql 是否达到了错误连接数的上限,如果是的,可以修改服务端配置,调大连接数,FLUSH HOSTS, 再尝试重新连接