mysql 8.0默认认证插件caching_sha2_password与旧客户端不兼容,需改用户插件、升级驱动或临时调整启动参数;sql模式更严格导致group by报错,应重写sql而非简单关闭;时区处理需显式配置客户端参数;connector/j 8.x驱动类、url参数和编码要求均与5.x不同。

MySQL 8.0 默认认证插件不兼容老客户端
MySQL 8.0+ 默认用 caching_sha2_password 认证插件,而很多旧版驱动(如 MySQL Connector/J 5.x、PyMySQL 0.9 以下、旧版 Navicat、DBeaver 默认配置)只认 mysql_native_password。连不上时常见错误是:Authentication plugin 'caching_sha2_password' cannot be loaded 或直接报错“Access denied”。
解决思路不是降级服务端,而是按需调整用户认证方式或升级驱动:
- 对临时调试或内部工具用户,可显式改用兼容插件:
ALTER USER 'username'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
- 生产环境建议升级客户端驱动:Java 用 Connector/J 8.0+,Python 用 PyMySQL ≥1.0 或 mysqlclient ≥2.0,Node.js 用 mysql2 ≥2.0
- 若必须保老驱动又不能改用户,可在 MySQL 启动时加
--default-authentication-plugin=mysql_native_password(仅限测试环境,不推荐长期使用)
MySQL 5.7 和 8.0 的 SQL 模式差异导致查询失败
MySQL 8.0 默认启用更严格的 sql_mode,比如包含 ONLY_FULL_GROUP_BY 和 STRICT_TRANS_TABLES,而很多老业务 SQL 习惯写 SELECT a, b FROM t GROUP BY a(没把 b 放进聚合或 GROUP BY),在 8.0 下直接报错:Expression #2 of SELECT list is not in GROUP BY clause。
别急着关 STRICT 模式——先确认是否真需要宽松行为:
- 查当前模式:
SELECT @@sql_mode;
- 临时修复(会话级):
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';(去掉ONLY_FULL_GROUP_BY) - 长期方案:重写 SQL,确保非聚合字段都在 GROUP BY 中,或用 ANY_VALUE(
b) 显式声明意图 - 注意:某些 ORM(如 Django 2.0+)依赖严格模式做类型校验,盲目关闭可能掩盖数据问题
不同语言客户端对时间类型处理不一致
MySQL 5.6/5.7 对 TIMESTAMP 和 DATETIME 的时区行为模糊,8.0 明确区分:前者存 UTC、读取转会话时区,后者纯字面值。Java 的 ResultSet.getTimestamp()、Python 的 cursor.fetchall() 在不配时区时容易拿到偏移错误的时间。
关键不在 MySQL 版本,而在客户端连接参数是否显式声明时区:
- JDBC 连接串必须加:
?serverTimezone=Asia/Shanghai&useTimezone=true(缺一不可) - Python + PyMySQL:初始化时传
timezone='Asia/Shanghai',或设init_command="SET time_zone = '+8:00'" - Go 的
github.com/go-sql-driver/mysql需在 DSN 加loc=Asia%2FShanghai - 不设时区时,
TIMESTAMP字段在跨时区部署下几乎必然出错,且难以复现
MySQL Connector/J 5.x 与 8.x 驱动的 URL 写法区别
老项目沿用 jdbc:mysql://host:3306/db 可能连不上 8.0,默认驱动类从 com.mysql.jdbc.Driver 换成 com.mysql.cj.jdbc.Driver,且 URL 解析逻辑变了。
最常踩的坑是参数名失效或含义反转:
-
useSSL=true在 5.x 是默认 true,在 8.x 默认 false,不显式写会报警告甚至拒绝连接(尤其启用了强制 SSL 的服务器) -
serverTimezone在 5.x 不生效,8.x 必须设,否则时间全乱 -
characterEncoding=utf8要换成characterEncoding=utf8mb4,否则 emoji 插入失败 - 驱动类加载方式变了:5.x 兼容
Class.forName("com.mysql.jdbc.Driver"),8.x 推荐直接用DriverManager.getConnection(...),自动发现
版本混用时,驱动实际行为取决于 classpath 里谁在前,而不是你写的类名——检查 mvn dependency:tree 或 jar 包内容比猜更靠谱。











