首选方案是重写sql使其符合only_full_group_by规则,而非禁用该模式;若必须临时绕过,应使用set session sql_mode=(select replace(@@sql_mode,'only_full_group_by','')),永久修改则需在my.cnf中显式配置完整sql_mode并重启服务。

直接改配置不是首选方案——ONLY_FULL_GROUP_BY被启用是MySQL 5.7.5+起的默认行为,关掉它会让原本语义模糊的查询“侥幸通过”,但结果不可控、不可复现,线上风险远大于临时绕过。
先确认是不是它在报错
别猜,执行这条命令看实际生效的模式:
SELECT @@sql_mode;
如果返回结果里包含 ONLY_FULL_GROUP_BY(通常排第一位),且错误信息末尾带 this is incompatible with sql_mode=only_full_group_by,那就坐实了。
- 云数据库如阿里云 RDS 通常限制
@@GLOBAL.sql_mode写权限,SET GLOBAL会直接报ERROR 1227 -
@@sql_mode输出是英文逗号+空格分隔的字符串,比如'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,...',注意空格不能忽略
临时禁用只该用于调试,且必须用正确写法
开发环境或CI流水线跑通时,只改当前会话最安全。断开重连自动还原,不影响其他连接:
SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
- 别手拼字符串,比如
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,...'—— 容易漏项,MySQL会自动补回默认集 - 别设空值
'',MySQL会强制恢复完整默认模式,ONLY_FULL_GROUP_BY还在 - JDBC 的
connectionInitSql可能被忽略,建议在应用首次 query 前显式执行一次
永久修改配置文件必须写全 sql_mode
仅限自建 MySQL,且必须重启服务才生效。在 my.cnf 的 [mysqld] 段下添加:
sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
- 必须显式列出全部项,不能省略、不能留空、不能只写
"",否则 MySQL 自动补回含ONLY_FULL_GROUP_BY的默认集 - Docker 环境需进容器编辑
/etc/mysql/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf,改完docker restart - Windows 是
my.ini,Linux/macOS 通常是/etc/my.cnf或/etc/mysql/my.cnf
真正容易被忽略的点:关了模式,结果还是不对
即使禁用了 ONLY_FULL_GROUP_BY,MySQL 仍可能从每组中任意选一行返回 id、name 等字段——这不是 bug,是行为暴露。同一查询两次执行,结果可能不同;主从之间也可能因选行策略差异导致不一致。业务上若依赖“某条记录的完整快照”,这种不确定性比报错更危险。











