caching_sha2_password首次连接慢是因rsa公钥协商需1–2轮往返及cpu加解密,后续复用连接或命中缓存则变快;root等管理账号在低配服务器、长密码、高rtt或未优化openssl时延迟更明显。

caching_sha2_password 插件在首次连接时会触发密钥交换和 RSA 加解密,比 mysql_native_password 多出 1–2 轮网络往返和 CPU 密码运算,导致管理账号(尤其是 root)登录延迟明显——这不是配置错误,而是 8.0 默认认证机制的固有行为。
为什么 root 登录第一次特别慢,后续又快了?
因为 caching_sha2_password 在首次连接时需完成公钥协商:客户端向服务端请求公钥 → 服务端返回 → 客户端用公钥加密密码再发回。这个过程涉及 RSA 加解密(尤其在低配服务器或高并发连接池初始化时更明显)。后续连接若复用同一连接或命中缓存,则跳过该流程。
验证方式:mysql -u root -p -h127.0.0.1 --protocol=tcp(强制走 TCP),观察首次输入密码后是否卡顿 1–3 秒;再执行一次相同命令,通常秒进。
- 仅本地 socket 连接(
-S /tmp/mysql.sock)可能不触发该流程,掩盖问题 - Navicat、DBeaver 等 GUI 工具默认走 TCP,更容易暴露延迟
- Java 应用若用
mysql-connector-java 8.0.28+且未显式指定allowPublicKeyRetrieval=true,会直接报错而非变慢
哪些管理账号最容易被拖慢?
所有使用 caching_sha2_password 且满足以下任一条件的账号:
- 密码长度 ≥ 20 字符(RSA 加密开销随明文长度增长)
- 运行在容器或云主机上,且未预装 OpenSSL 优化库(如 libssl1.1 或更高)
- 通过跳板机或代理连接,增加 RTT,放大握手耗时
- root 用户未设密码(空密码触发 fallback 行为,反而更不稳定)
注意:SHOW CREATE USER 'root'@'localhost' 中的 IDENTIFIED WITH caching_sha2_password 是明确信号;而 SELECT plugin FROM mysql.user WHERE User='root' 返回 caching_sha2_password 也同理。
不改插件,怎么让登录快起来?
保留 caching_sha2_password 安全性的同时降低延迟,优先尝试这些实操项:
- 在连接串中加参数:
?allowPublicKeyRetrieval=true&useSSL=false(测试环境可用;生产环境建议配好 TLS 后关掉allowPublicKeyRetrieval) - 升级客户端驱动:Java 用
mysql-connector-j 8.0.33+,Python 用mysqlclient 2.2.0+或PyMySQL 1.1.0+,它们对公钥缓存做了优化 - 给 root 用户显式指定短密码(如 12 位随机字符),避免长密码触发多块 RSA 加密
- 禁用 RSA 公钥分发(若确定所有客户端可离线获取公钥):
SET PERSIST block_encryption_mode='aes-128-ecb';不起作用——正确做法是启动时加--caching-sha2-password-public-key-path=/path/to/public_key.pem并在客户端预置
为什么 ALTER USER … IDENTIFIED WITH mysql_native_password 不总生效?
常见失效场景:
- 用户 host 匹配不精确:你改了
'root'@'localhost',但应用连的是'root'@'127.0.0.1'(二者在 MySQL 中视为不同账号) - 未刷新权限:
FLUSH PRIVILEGES必须执行,否则内存中缓存的 plugin 信息不变 - 配置文件覆盖:如果
my.cnf里写了default_authentication_plugin=caching_sha2_password,新创建用户仍会继承该插件 - Docker 环境中,
mysql:8.0镜像启动时若传了MYSQL_ROOT_PASSWORD,会自动创建 root 用户并强制用caching_sha2_password,ALTER USER 必须在容器启动后立即执行
真正保险的做法是双管齐下:改用户插件 + 改全局默认值,再重启 mysqld(或至少 reload)。
真正容易被忽略的是:**管理账号变慢往往不是孤立现象,而是和连接池初始化、CI/CD 自动化脚本、监控探针重试逻辑耦合在一起**。比如 Jenkins 每次构建都新建 root 连接,每次都会卡 2 秒;Prometheus 的 mysqld_exporter 若配置了 5 秒抓取间隔,可能因超时反复重试,进一步加重服务端负担。这类问题不会出现在单条mysql -u root -p 命令里,但在线上系统中影响真实。











