mysql 8.0默认使用caching_sha2_password插件加密密码,采用sha-256加盐哈希并缓存认证状态;旧客户端因不兼容该插件而无法连接,需通过alter user切换为mysql_native_password或配置default_authentication_plugin。

MySQL 8.0 默认用 caching_sha2_password 插件加密密码
新装的 MySQL 8.0+ 实例,用户密码不是明文存的,也不是老版本的 mysql_native_password 哈希,而是走 caching_sha2_password 插件——它用 SHA-256 加盐哈希,并缓存认证状态来提速。
这意味着:旧客户端(比如 MySQL 5.7 客户端、某些老版 PHP mysqli 扩展、未更新的 Navicat)连不上,报错通常是 Authentication plugin 'caching_sha2_password' cannot be loaded 或直接卡在连接阶段。
- 检查当前用户用的插件:
SELECT user, host, plugin FROM mysql.user WHERE user = 'your_user'; - 如果返回
caching_sha2_password,而你的应用连不上,大概率是客户端不兼容 - 该插件要求 TLS 或安全通道下传输明文密码(用于服务端再哈希),所以非 SSL 连接时,部分客户端会拒绝发送密码
改回 mysql_native_password 的实操步骤
不是所有环境都能立刻升级客户端,临时或长期切回老插件更实际。注意:这不是“降级安全”,而是权衡兼容性;SHA-256 本身更安全,但若连都连不上,安全无从谈起。
- 创建用户时指定:
CREATE USER 'u1'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd123'; - 修改已有用户:
ALTER USER 'u1'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd123'; - 执行后必须
FLUSH PRIVILEGES;,否则内存缓存没更新,新配置不生效 - 如果用
SET PASSWORD FOR 'u1'@'%' = 'xxx';,它会沿用当前用户的plugin,不会自动切插件
default_authentication_plugin 配置项只影响新用户,不改旧用户
很多人在 my.cnf 里加了 default_authentication_plugin = mysql_native_password 就以为万事大吉,结果发现老用户还是连不上——因为这个配置只对后续 CREATE USER 生效,已存在的用户 plugin 字段不变。
- 配置位置:通常在
[mysqld]段下,改完要重启 MySQL(systemctl restart mysqld) - 验证是否生效:
SHOW VARIABLES LIKE 'default_authentication_plugin'; - 它不影响
root用户(尤其是初始化时自动生成的),root的插件得单独ALTER USER - Docker 环境注意:镜像启动时若用
MYSQL_ROOT_PASSWORD,root 用户仍可能被设为caching_sha2_password,需进容器手动改
客户端连接时显式指定 --default-auth 可绕过服务端插件协商
有些场景不能动服务端(比如云数据库 RDS 只读实例、DBA 不放权),但你本地开发要用老客户端,这时可以在命令行强制指定认证方式。
- MySQL CLI 连接:
mysql -u u1 -p --default-auth=mysql_native_password -h xxx.rds.aliyuncs.com - Python pymysql 示例:
conn = pymysql.connect(..., auth_plugin_map={'mysql_native_password': 'pymysql._auth.mysql_native_password'})(需较新版本支持) - Java JDBC URL 加参数:
?serverTimezone=UTC&allowPublicKeyRetrieval=true&useSSL=false—— 注意allowPublicKeyRetrieval=true是为了配合caching_sha2_password的公钥交换流程,不是为了关安全 - 这个方法治标不治本,每次连接都要带参数,CI/CD 脚本容易漏,建议仅作临时调试用
真正麻烦的是那些封装了连接逻辑的 ORM 或中间件,它们未必暴露认证插件选项,这时候只能倒逼服务端适配或升级客户端驱动。密码加密机制本身不复杂,难的是插件、客户端、网络链路三者之间的隐式契约——少一环,就卡在“连不上”这一步。











