druid连接mysql 8.0报错caching_sha2_password不支持,本质是认证失败而非超时;根本原因是老版druid不识别该插件,需升级jdbc驱动并配置allowpublickeyretrieval=true,或降级用户认证方式为mysql_native_password。

Druid 连接 MySQL 8.0 报错 caching_sha2_password 不支持
这不是连接超时,是认证失败——Druid(尤其老版本)压根不识别 MySQL 8.0 默认的 caching_sha2_password 插件,直接拒绝握手,日志里常出现 Unknown system variable 'caching_sha2_password' 或 Public Key Retrieval is not allowed。连接根本没建立,自然谈不上“超时”。
解决路径只有两条:
- 改服务端:把用户认证方式降级为
mysql_native_password(快速验证用) - 改客户端:升级 JDBC 驱动 + 显式启用公钥获取(生产推荐)
执行降级命令前,确认你有 ALTER USER 权限:
ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';
注意:@'%' 要和你应用连接时用的实际 host 一致;改完必须 FLUSH PRIVILEGES;。
JDBC URL 必须显式启用 allowPublicKeyRetrieval=true
即使用了 8.x 驱动(如 mysql-connector-java-8.0.33.jar),默认仍禁用公钥获取,而 caching_sha2_password 认证依赖它完成密钥交换。不加这个参数,连接会卡在 SSL 握手阶段,表现就像“超时”。
URL 示例(关键参数已加粗):
jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC&<strong>allowPublicKeyRetrieval=true</strong>&characterEncoding=UTF-8
常见漏掉的坑:
-
useSSL=false和allowPublicKeyRetrieval=true必须同时存在,否则驱动可能抛出SSL connection error - MySQL 8.0.28+ 版本中,
allowPublicKeyRetrieval默认为false,且无法通过配置文件绕过,只能写在 URL 里 - 如果数据库启用了强制 SSL,那就不能关
useSSL,得配好证书并设requireSSL=true
Druid 配置里别漏掉 connectionProperties 的字符集与时区
认证通过后,还可能因字符集或时区不一致触发隐式等待甚至中断。比如 characterEncoding=UTF-8 缺失,Druid 在初始化连接时会反复尝试协商编码,拖慢建连速度;serverTimezone 没对齐,某些 timestamp 操作会触发时区转换阻塞。
Druid 的 connectionProperties 应至少包含:
useUnicode=true;characterEncoding=UTF-8;serverTimezone=Asia/Shanghai
注意:
- 多个属性用分号
;分隔,不能用 & —— 这是 JDBC URL 和连接池 properties 的语法区别 -
serverTimezone值必须是 IANA 时区名(如Asia/Shanghai),不能写GMT+8或CST,否则驱动解析失败 - 该配置只影响连接初始化阶段,不影响运行时 SQL 执行
MySQL 服务端 wait_timeout 和 interactive_timeout 不要盲目调小
有人看到连接“超时”,第一反应是把 MySQL 的 wait_timeout 从默认 28800 秒(8 小时)砍到 60 秒——这反而会让 Druid 连接池里的空闲连接频繁失效,触发大量重连,放大问题。
正确做法是让服务端 timeout ≥ 客户端连接池的空闲回收周期。例如 Druid 配了 timeBetweenEvictionRunsMillis=60000(1 分钟检测一次),那 MySQL 的 wait_timeout 至少设为 120 秒以上。
临时调整命令(重启失效):
SET GLOBAL wait_timeout = 300;<br>SET GLOBAL interactive_timeout = 300;
真正需要持久化时,改 /etc/my.cnf 的 [mysqld] 段:
wait_timeout = 300<br>interactive_timeout = 300
重点:这两个值对所有连接生效,改之前先查当前活跃连接数,避免误杀长事务。











