一台 MySQL 5.6 跑了四年,数据 1.8 G,想升到 8.0。备份完之后导进去,站点直接 500。
错误日志里全是这个:
SQLSTATE[HY000]: General error: 1055 Expression #1 of SELECT list
is not in GROUP BY clause and contains nonaggregated column
四个坑,挨个说。
一、ONLY_FULL_GROUP_BY
MySQL 5.6 的默认 sql_mode 是空的。GROUP BY 可以随便查不在分组里的列,取哪一行由它自己决定。
8.0 默认开了 ONLY_FULL_GROUP_BY,这种写法直接报错。
先看当前模式:
SELECT @@sql_mode;
8.0 出来是一长串:
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,
NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
两个选择:改 SQL,或者关掉这个模式。
长期看肯定要改 SQL。但 WordPress 生态里一堆老插件写死了这种查询,短期只能先关:
[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
写进 /etc/my.cnf,重启生效。注意别整段清空,STRICT_TRANS_TABLES 还是有用的,能挡住字段超长这类脏数据。
二、NO_ZERO_DATE
这是白屏的另一个来源。WordPress 有些老表(尤其是插件建的)字段默认值是 0000-00-00 00:00:00,8.0 严格模式下插入直接报错。
先查有没有这种行:
SELECT COUNT(*) FROM wp_posts
WHERE post_date = '0000-00-00 00:00:00';
有的话先修数据再升级:
UPDATE wp_posts SET post_date = '1970-01-01 00:00:00'
WHERE post_date = '0000-00-00 00:00:00';
不改的话,导数据那一步就会卡住。
三、认证插件 caching_sha2_password
8.0 把默认认证插件从 mysql_native_password 换成了 caching_sha2_password。老版本 PHP 的 mysqli 不认,报:
mysqli_real_connect(): The server requested authentication
method unknown to the client [caching_sha2_password]
三个办法,推荐第三个:
- 全局降级认证插件(不推荐,安全性下降)
- 升级 PHP 到 7.4 以上
- 只给 WordPress 这个用户单独设回 native
ALTER USER 'wpuser'@'localhost'
IDENTIFIED WITH mysql_native_password BY '你的密码';
FLUSH PRIVILEGES;
这样其他账号还是新插件,只有 WordPress 用老的。兼容性和安全性取个中间值。
四、排序规则变了
5.6 用 utf8mb4_general_ci,8.0 默认 utf8mb4_0900_ai_ci。两个影响:
第一,JOIN 两个不同排序规则的字段会报错:
Illegal mix of collations (utf8mb4_general_ci,IMPLICIT)
and (utf8mb4_0900_ai_ci,COERCIBLE) for operation '='
第二,大小写和重音的判断变严了。原来某些比较里 Abc 和 abc 算相等,现在不一定。
最稳的做法是新建库时显式指定成老排序规则,让整库保持一致:
CREATE DATABASE wp DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
导出导入两边都带字符集参数,能避免 90% 的乱码:
mysqldump --default-character-set=utf8mb4 -u root -p wp > wp.sql
mysql --default-character-set=utf8mb4 -u root -p wp < wp.sql
五、GROUP BY 不再隐式排序
这个最阴。不报错,只是结果顺序变了。
5.6 里 GROUP BY 会顺带按分组字段排序,8.0 取消了。所以原来"按时间倒序"的列表,升级后变成乱序,分页跟着乱。
解决很简单,SQL 里显式写 ORDER BY:
SELECT post_id, COUNT(*) AS c FROM wp_down
GROUP BY post_id ORDER BY MAX(create_time) DESC
如果代码不是你的,就只能加补丁,或者忍受乱序。
升级步骤
顺序很重要,别直接动生产库:
- 全量备份,
mysqldump和物理文件各一份 - 测试机装 8.0,导入数据
- 跑一遍站点,重点看后台列表页、分页、搜索
- 记录所有报错,改 SQL 或者调
sql_mode - 生产环境停站 30 分钟,重复步骤 2 到 3
- 开一小时
general_log,盯着有没有静默失败
| 项目 | 5.6 表现 | 8.0 表现 | 影响 |
|---|---|---|---|
| GROUP BY 非聚合列 | 随便取一行 | 报 1055 错误 | 页面 500 |
| 零日期字段 | 能插入 | 报错 | 写入失败 |
| 认证插件 | native | caching_sha2 | 连不上库 |
| 排序规则 | general_ci | 0900_ai_ci | JOIN 报错、乱码 |
| GROUP BY 排序 | 隐式升序 | 无序 | 分页错乱 |
升级数据库最大的风险不是"升不上去",而是"升上去了,但某条查询悄悄变了结果"。报错的都好办,不报错的才要命。
1、本站所有资源均收集于互联网,分享目的仅限学习与参考。如有侵权,请联系 1685698671@qq.com 及时删除!
2、本站资源不保证完整性和安全性,下载后请自行检测。使用过程中出现的任何问题均与本站无关,敬请自行处理。
3、本站资源仅限个人学习研究使用,严禁用于任何违法违纪用途。因使用者违规使用产生的一切后果,由使用者自行承担,本站不承担任何责任。


评论(0)