P11 · MySQL 驱动版本过旧:Client does not support authentication protocol
场景还原:项目一直用的老 MySQL 5.x,今天 DBA 把数据库升级到了 MySQL 8.0------代码一行没改,连接直接崩了:
MySQLNonTransientConnectionException: Client does not support authentication protocol requested by server; consider upgrading MySQL client大白话:你手里的驱动是"老古董",服务器换了新的"验票方式",老驱动不认。
一、问题现象
(复现环境:驱动用老版本 mysql-connector-java-5.1.13,服务端是 MySQL 8.0.35)
驱动加载成功,连接 MySQL 8 ...
>>>> 连接失败,看下面的异常信息:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Client does not support authentication protocol requested by server; consider upgrading MySQL client
at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3566)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3498)
...

二、出错代码
java
import java.sql.*;
public class OldDriverDemo {
public static void main(String[] args) {
try {
// 5.x 老驱动的类名是 com.mysql.jdbc.Driver
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3307/testdb", "root", "root123");
System.out.println("连接成功: " + conn);
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
编译运行用的驱动:mysql-connector-java-5.1.13.jar(2011 年的老版本),服务端:MySQL 8.0。
三、为什么会这样
MySQL 8.0 把默认认证插件 从老的 mysql_native_password 换成了更安全的 caching_sha2_password。这相当于服务器换了新的"验票机":
- 新版驱动(mysql-connector-j 8.x)认识新验票机,正常通过;
- 老版驱动(5.x)只会老的
mysql_native_password验票方式,看到新验票机直接懵了:"你这是什么验票方式?我不支持!" → 于是报Client does not support authentication protocol requested by server。
类似的"驱动和服务器不匹配"还有这些表现:
- MySQL 8 服务器 + 老驱动 → 上面的认证协议错误(最常见);
- 老驱动 + 新版连接参数(
useSSL、serverTimezone等)→ 各种奇怪的 "Unknown system variable" / 参数解析错误; - 反过来:新驱动连老 MySQL 一般没事(向下兼容),但太老的 5.1 服务器也可能有新问题。
四、怎么解决
正解:把驱动升级到与 MySQL 8 匹配的新版 (mysql-connector-j 8.0.x),并且类名也要换成新的:
xml
<!-- 用 8.x 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
java
// 类名也要用 8.x 的新写法(旧 com.mysql.jdbc.Driver 在新驱动里只是个兼容壳)
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3307/testdb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true",
"root", "root123");
三个常见参数说明:
useSSL=false(本地/内网测试关掉 SSL 省事)、serverTimezone=Asia/Shanghai(8.x 驱动要求明确时区,详见 P12)、allowPublicKeyRetrieval=true(caching_sha2_password 需要,本地测试常见)。
如果是老项目暂时没法升级驱动,应急方案是在数据库侧把该账号的认证方式改回老插件(不推荐长期用,仅应急):
sql
-- 在 MySQL 里执行(DBA 操作):把某个账号降级为老认证方式
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root123';
怎么判断驱动版本? 看你的依赖/ jar 名就知道:
mysql-connector-java-5.1.x.jar/mysql-connector-java-8.0.x.jar→ 老命名(8.0 早期)mysql-connector-j-8.0.x.jar→ 新命名(官方 8.0.31 后改的名)
五、防坑总结
- 服务器 MySQL 8,驱动必须 8.x(
mysql-connector-j),类名用com.mysql.cj.jdbc.Driver; - 升级数据库后"连不上了"优先怀疑驱动版本,别先怀疑代码;
- 看到 "Client does not support authentication protocol" = 驱动太老,升级驱动;
- 老驱动能连老库,就别乱升级------先看服务器版本再选驱动版本;
- 应急的
mysql_native_password降级只是过渡,最终要升级驱动。