小鲸使用 MySQL 客户端(Navicat/HeidiSQL/SQLyog)连接公司远程 MySQL 服务器的时候按照正常的流程 设置远程地址 > 账号密码 > 连接 发现没有办法正常连接该服务器, 报了个 1045 错误,并且连接地址也有点不寻常…


背景:

  • 远程 MySQL 服务器 192.168.1.200 [email protected]
  • 本机 IP 192.168.1.117
  • 远程 MySQL 版本 8.0

小鲸先确定了几个情况:

  • 远程 MySQL 正常访问(服务本身正常 + 本机可连通)
  • 连接的账密和权限没有问题

问题

连接 192.168.1.200 报 1045 错误

MySQL 连接报错

分析

问题就出在这个 1045 上,按照提示的说法是:使用 root 用户连接 192.168.1.117 被拒绝访问

乍一看好像是密码或者权限有问题,仔细看就可以知道问题出在连接地址上。

为什么我链接的地址明明是 192.168.1.200 现在却变成了我本地的 IP 呢? 😳

这个时候我怀疑是不是客户端和服务器闹矛盾不和?

我就接连换了 HeidiSQL、SQLyog 得到的结果都是一样的:失败 😂

HeidiSQL 连接报错

小插曲

这里有一个小插曲,我们看上一张图 HeidiSQL 有个选择 Library 的选项,意思就是可以切换用来连接的驱动库,有意思的是使用默认的 libmariadb.dll 无法连接,但是切换到 libmysql-6.1.dll 的时候竟然可以成功连接那台该死的远程 MySQL!

HeidiSQL 切换驱动库

到这里可能您会认为这是解决方案,但其实不是,这个只是一个暂时的解决方案!并不是所有的 MySQL 客户端都能切换驱动库!

🤔 这里我陷入的沉思,为什么这个驱动可以连接,而其他所有默认的驱动都不能呢?

这里我就开始怀疑是 远程 MySQL 的问题了,毕竟其他的远程 MySQL 都可以唯独这台不行!

通过一顿排查,某个项目中使用这个远程 MySQL 服务的 JDBC 连接串是这样的

jdbc:mysql://192.168.1.200:3306/SOME_DB?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=true&requireSSL=false&verifyServerCertificate=false&serverTimezone=GMT%2B8

睿智的小鲸发现了盲点 😏

有几个参数不寻常,单独拎出来

useSSL=true&requireSSL=false&verifyServerCertificate=false

这里指定连接的时候使用 SSL,是你!原来是远程 MySQL 开启了 SSL 访问,而我在使用客户端连接的时候并没有以这种方式连接!

解决

知道了原因,解决方法也就水到渠成了:使用 SSL 连接这个远程 MySQL 服务器

navicat 连接时使用 SSL 连接

HeidiSQL 使用 SSL 连接

扩展

之前在自己搭建或者使用的时候基本没有碰到要开启 SSL 的情况,有关开启 SSL 可以参考 你的 MySQL 服务器开启 SSL 了吗? - 茁壮的小草 - 博客园 会得到一些启示。

虽然 SSL 方式使得安全性提高了,但是相对地使得 QPS 也降低 23% 左右。所以要谨慎选择:
对于非常敏感核心的数据,或者 QPS 本来就不高的核心数据,可以采用 SSL 方式保障数据安全性;
对于采用短链接、要求高性能的应用,或者不产生核心敏感数据的应用,性能和可用性才是首要,建议不要采用 SSL 方式;