MySQL 8.0升级后GROUP BY报错因默认启用ONLY_FULL_GROUP_BY,需确保SELECT字段在GROUP BY中或被聚合函数包裹;JSON函数更严格,路径键名须双引号;mysql_upgrade不处理用户对象依赖;默认认证插件变更导致客户端连接失败。

MySQL 8.0 升级后 GROUP BY 报错:Expression #1 of SELECT list is not in GROUP BY clause
这是最典型的兼容性断裂点。MySQL 5.7 默认是 ONLY_FULL_GROUP_BY 关闭的,8.0 开启了——不是 bug,是 SQL 标准更严格了。
常见错误现象:ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause...
- 别急着关 SQL 模式,先检查业务 SQL 是否真合规:SELECT 的字段要么在
GROUP BY中,要么被聚合函数包裹(如MAX()、COUNT()) - 如果确认逻辑无误(比如只查单值分组),可临时调整会话级别:执行
SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','')); - 全局修改要谨慎:编辑
my.cnf,在[mysqld]下加sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"(显式剔除ONLY_FULL_GROUP_BY) - 注意:某些 ORM(如旧版 Django、Laravel Eloquent)生成的 SQL 可能隐含非确定性字段,升级后必须重审查询逻辑
升级后 json_extract() 返回 NULL 或类型异常
MySQL 5.7 的 JSON 函数对路径语法容忍度高,8.0 更严格;同时默认字符集从 utf8 变成 utf8mb4,影响 JSON 字符解析。
常见错误现象:原 JSON_EXTRACT(col, '$.name') 突然返回 NULL,或 JSON_CONTAINS() 失效
- 检查 JSON 字段是否真合法:用
JSON_VALID(col)验证,很多老数据是字符串伪装 JSON,升级后校验变严 - 路径表达式必须用双引号包裹键名:错误写法
'$.user.id'→ 正确写法'$.user."id"'(尤其键含数字、短横线时) - 避免隐式转换:
JSON_EXTRACT()返回的是 JSON 类型,不是字符串;需要字符串请用JSON_UNQUOTE(JSON_EXTRACT(...)) - 表字符集若仍是
utf8,JSON 中 emoji 或生僻字可能被截断,导致解析失败;建议全库升级为utf8mb4
mysql_upgrade 执行完还是报错:Table doesn't exist 或 Unknown column
这个命令只更新系统表结构和权限表,不处理用户库中的视图、存储过程、触发器等依赖元数据的对象。
常见错误现象:ERROR 1146 (42S02): Table 'mysql.proc' doesn't exist 或自定义视图报 Unknown column 'xxx' in 'field list'
- 先确认
mysql_upgrade是否真正成功运行:它会在日志里输出 “Finished upgrading MySQL tables”,没看到就失败了 - 手动刷新权限表:执行
FLUSH PRIVILEGES;,再检查mysql.user表结构是否含新字段(如password_expired) - 重建依赖系统表的视图:比如老视图用了
mysql.proc,而 8.0 已移除该表,改用information_schema.ROUTINES;需 DROP + CREATE 替换 - 存储过程/函数中引用了已删除列(如
plugin列在mysql.user中被拆分),必须重写逻辑,不能只靠mysql_upgrade自动修复
客户端连不上:Authentication plugin 'caching_sha2_password' cannot be loaded
MySQL 8.0 默认认证插件从 mysql_native_password 换成 caching_sha2_password,但很多老客户端(尤其是 PHP 7.2 以下、MySQL Connector/J 5.x)不支持。
常见错误现象:Client does not support authentication protocol requested by server
- 临时方案(开发环境可用):创建用户时指定旧插件:
CREATE USER 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'p'; - 长期方案是升级客户端驱动,但要注意:PHP 7.4+、Connector/J 8.0+ 才完整支持新插件
- 别改全局默认插件(
default_authentication_plugin=mysql_native_password),这等于放弃 8.0 的安全增强,且未来版本可能移除该配置项 - 如果用 Docker,确认镜像 tag 是
8.0而非latest——后者可能已是 8.4,认证机制又有变化


















