MySQL 5.7 升级到 8.0 后 GROUP BY
报错:Expression #1 of SELECT list is not in GROUP BY clause
这是升级后最典型的兼容性断裂点。MySQL 8.0 默认启用
sql_mode=ONLY_FULL_GROUP_BY,而 5.7 很多环境是关闭的。一旦查询中
SELECT的字段没出现在
GROUP BY子句里,就会直接报错。 临时修复:执行
SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));(仅当前会话) 长期方案:重写 SQL,确保所有非聚合字段都显式出现在
GROUP BY中;或检查应用层 ORM 是否生成了隐式依赖旧模式的语句 注意:不要在生产配置文件里粗暴删掉
ONLY_FULL_GROUP_BY—— 它能暴露逻辑歧义,比如
SELECT name, MAX(age) FROM user GROUP BY dept_id中
name可能对应多个值,结果不可预测
CREATE TABLE
中 DATETIME
默认值为 CURRENT_TIMESTAMP
在 8.0 不再合法
MySQL 5.6/5.7 允许对
DATETIME字段设置
DEFAULT CURRENT_TIMESTAMP,但这是非标准行为;8.0 严格区分
TIMESTAMP和
DATETIME的默认值能力,仅
TIMESTAMP支持该语法。 错误示例:
CREATE TABLE t (ts DATETIME DEFAULT CURRENT_TIMESTAMP);→ 报错
Invalid default value for 'ts'兼容写法:改用
TIMESTAMP类型,或显式用触发器/应用层填充时间 注意:如果表结构由 ORM 自动生成(如 Django、Laravel),需确认其 MySQL 8.0 兼容版本,老版本可能仍硬编码该非法语法
系统变量名变更导致 my.cnf
启动失败
MySQL 8.0 废弃并重命名了一批配置项,例如
query_cache_type已被彻底移除(Query Cache 在 8.0 中删除),
explicit_defaults_for_timestamp默认值变为
ON,且不再接受
OFF值。 常见症状:升级后 mysqld 无法启动,错误日志出现
unknown variable 'query_cache_type=0'或
Invalid argument: explicit_defaults_for_timestamp操作建议:用
mysqld --verbose --help | grep -A 1 "Default options"查看当前版本实际支持的变量;逐行比对旧
my.cnf,注释或删除已废弃项 特别注意:某些云数据库(如阿里云 RDS)控制台仍显示旧参数名,但后台已屏蔽,不能盲目照填
JSON 字段索引语法差异:从 GENERATED COLUMN
到 JSON_VALUE
5.7 中常通过虚拟列 + 索引模拟 JSON 字段子键查询,例如:
ALTER TABLE t ADD COLUMN j_name VARCHAR(100) AS (json_unquote(json_extract(data, '$.name'))) STORED, ADD INDEX idx_name(j_name);。8.0 引入
JSON_VALUE()函数,并支持直接在函数表达式上建索引,但语法更严格。 8.0 正确写法:
CREATE INDEX idx_name ON t (JSON_VALUE(data, '$.name' RETURNING CHAR(100)));不兼容点:5.7 的
json_extract返回 JSON 类型,而 8.0 要求
JSON_VALUE显式声明返回类型,否则建索引失败 风险提示:升级后原有虚拟列索引仍可用,但若应用改用新语法,需验证查询是否命中索引(
EXPLAIN看
key列) 升级不是“换二进制就行”的事,真正卡住的往往是那些跑了一年没动过、但恰好踩在废弃边界上的 SQL 或配置项。建议先用
mysql_upgrade(8.0.16+ 已弃用,改用
mysqld --upgrade)扫描兼容性问题,再结合慢日志和应用错误监控定向修复。
