在正常项目开发过程中,如果MySQL版本从5.6升级到5.7版本,作为DBA在考虑数据库版本升级带来的影响时,一般会有几个注意点:
-
sql_mode 默认值的改变
-
optimizer_switch 值的改变
-
备库升级影响主备复制
本文主要内容是MySQL升级到5.7版本之后,由于默认的 sql_mode 值带来的坑以及对应的解决方案。
| 案例一:ONLY_FULL_GROUP_BY
问题描述
MySQL版本从5.6升级至5.7之后,部分SQL执行报错,报错信息如下:
ERROR 1055 (42000): Expression #3 of XXXXXX list is not in GROUP BY clause and contains nonaggregated column ‘XXXXX.XXXXXX’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
这个问题原因在于从5.6升级至5.7版本后 sql_mode 默认值发生了改变,在5.7版本的 sql_mode 默认值中有意向 ONLY_FULL_GROUP_BY,该选项的含义表示:对于使用 GROUP BY 进行查询的SQL,不允许 SELECT 部分出现 GROUP BY 中未出现的字段,也就是 SELECT 查询的字段必须是 GROUP BY中出现的或者使用聚合函数的或者是具有唯一属性的。
解决方案
-
方案一(不推荐):修改5.7版本 sql_mode 值,将 ONLY_FULL_GROUP_BY 去掉
ONLY_FULL_GROUP_BY 是加强SQL规范的,其目的是让SQL查询出来的结果更符合规范,更准确。
如果没有 ONLY_FULL_GROUP_BY 规范限制,那么则能允许以下SQL的执行:SELECT a,b,c FROM t GROUP BY a。SQL按照a字段值进行分组,当同一个a字段值对应多个b或者c值时,查询结果中的b,c值是不确定的。 -
方案二:对于不符合ONLY_FULL_GROUP_BY限制的字段,添加unique索引
-
方案三:改写SQL,按照规范编写SQL
-
方案四:使用ANY_VALUE(),对于不符合ONLY_FULL_GROUP_BY的字段使用ANY_VALUE()函数,让MySQL跳过ONLY_FULL_GROUP_BY检测
mysql> SELECT name, address