直接结论:rsa密钥交换在mysql主从复制中必然失败,因io线程依赖c客户端库且不支持jdbc参数,受密钥配置、网络中间件及云服务限制;降级插件或升级客户端才是实际可行路径。

直接结论:不要指望在复制或旧客户端场景下“配通”caching_sha2_password的RSA握手流程——它在绝大多数生产链路里根本走不通,降级插件或升级客户端才是实际可行路径。
为什么RSA密钥交换在复制中必然失败
MySQL复制线程(IO_THREAD)底层调用的是 C 客户端库(libmysqlclient),不走 JDBC/ODBC 层,也不读取 allowPublicKeyRetrieval=true 这类 JDBC 参数。它依赖服务端主动提供公钥,而该机制要求:
- 主库必须已生成并加载 RSA 密钥对(
sha256_password_private_key_path/sha256_password_public_key_path) - 从库能直连主库的 3306 端口,并在首次握手时额外发起一次 TCP 请求获取公钥(不是复用原连接)
- 中间不能有 NAT、云 LB、ProxySQL 或任何会丢弃非标准包的中间件
- 阿里云 RDS、腾讯云 CDB 等托管服务默认禁用该功能,且不开放配置入口
只要满足其中任一限制,就会卡在 Lost connection during authentication 或静默超时,日志里看不到明确错误,只表现为复制延迟突增或 IO_THREAD 一直 Connecting。
ALTER USER 降级插件时最常踩的三个坑
执行 ALTER USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'xxx' 后仍失败,大概率是以下原因:
- 没查清实际连接的用户:运行
SELECT user, host FROM mysql.user WHERE user = 'repl';,确认host值是否匹配('repl'@'192.168.10.%'≠'repl'@'%') - 漏改 root 用户:复制常用
root账号,但root@localhost和root@127.0.0.1是两个独立账户,必须分别执行 ALTER - 云数据库限制:阿里云 RDS 执行 ALTER 会报
ERROR 1820 (HY000),需先用临时密码重置再改插件,且部分版本禁止IDENTIFIED WITH
Java 应用连主库没问题,但从库复制还是断——为什么?
因为应用连接和复制连接完全隔离:JDBC URL 加了 allowPublicKeyRetrieval=true&useSSL=false 只影响应用线程,不影响 MySQL 自身的复制协议。复制线程不解析 URL 参数,也不加载 JVM 配置。此时唯一有效动作是:
- 在主库上对复制账号执行插件降级(如上)
- 确保从库
my.cnf中未设置require_secure_transport=ON(否则即使插件降级也会被拒绝) - 检查从库 MySQL 版本:5.7 从库无法解析 caching_sha2_password 握手包,必须主从都 ≥ 8.0.4 才可能启用该插件
真正需要长期启用 caching_sha2_password 的前提
这不是一个“开了就更安全”的开关,而是一套基础设施约束:
- 主从均为 MySQL 8.0.28+(修复早期 caching_sha2_password 的内存泄漏和 handshake race)
- 网络直连,无任何中间设备干扰二次 TCP 握手
- 所有客户端(包括监控脚本、备份工具、ETL 工具)都升级到支持 RSA 公钥交换的驱动版本
- 已部署并验证 TLS 证书,且
require_secure_transport=ON已启用
现实中,90% 的线上 MySQL 复制链路不满足以上任意一条。强行推进只会把问题从“连不上”变成“连得慢且不稳定”。安全性和可用性冲突时,先保链路通,再逐步加固——比如先用 mysql_native_password + SSL,再过渡到全链路 TLS + caching_sha2_password。











