新电商项目选MySQL 8.0需关闭caching_sha2_password插件、重置sql_mode为兼容严格模式、禁用降序索引;否则注册/订单插入可能失败。

新电商项目直接选 MySQL 8.0,但必须关掉 caching_sha2_password 插件、显式重置 sql_mode、禁用默认的降序索引行为——否则上线当天就可能卡在用户注册或订单插入环节。
MySQL 8.0 默认认证方式会断掉老客户端连接
MySQL 8.0 默认使用 caching_sha2_password 认证插件,而多数 Java(mysql-connector-java 8.0.28 以下)、PHP(mysqli 扩展旧版本)、Node.js(mysql2 v2.2 之前)默认不支持该插件,连接时直接报错:Client does not support authentication protocol requested by server。
- 临时解法:启动时加
--default-authentication-plugin=mysql_native_password - 长期方案:升级驱动 + 在用户创建时显式指定插件:
CREATE USER 'app'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd' - 注意:不能只改
my.cnf里的插件配置,已存在的 root 或应用账号仍保留原插件,需单独ALTER USER ... IDENTIFIED WITH ...
sql_mode 变更会让 INSERT/UPDATE 突然失败
MySQL 8.0 默认 sql_mode 启用了 STRICT_TRANS_TABLES 和 NO_ZERO_DATE,而电商系统里大量存在类似 INSERT INTO orders (created_at) VALUES ('0000-00-00') 或字段超长被截断的写法,在 5.7 里只是警告,8.0 直接报错中断事务。
- 最稳妥做法:在初始化实例时就设置
sql_mode = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"(即去掉NO_ZERO_DATE等激进项,但保留核心严格模式) - 避免用
SET GLOBAL sql_mode = ...动态修改,它不持久,重启后失效;必须写入my.cnf或用SET PERSIST - 特别注意 MyBatis 的
useGeneratedKeys+keyProperty组合,在 strict 模式下若主键未设默认值且未传入,会因 NULL 插入失败
JSON 字段查询性能差异极大,别信“开箱即用”
电商订单表常把扩展属性存为 JSON,比如 extra ->>'$.user_level'。MySQL 5.7 对这类查询只能全表扫描;MySQL 8.0 支持虚拟列+索引,但必须手动建,不会自动优化。
- 正确姿势:先加虚拟列
ALTER TABLE orders ADD COLUMN user_level TINYINT AS (extra->>'$.user_level') STORED,再建索引CREATE INDEX idx_user_level ON orders(user_level) - 别用
GENERATED ALWAYS AS不带STORED—— 非持久化虚拟列无法建索引 - 多值场景(如
tags数组)要用MEMBER OF()+ 多值索引:CREATE INDEX idx_tags ON orders((CAST(extra->'$.tags' AS CHAR(1000)))); - 测试发现:同样千万级订单表,没建虚拟列时查询耗时 3.2s;建好后降到 18ms
窗口函数能简化分页和排名,但别在大表上滥用
电商后台常用“按销量 Top 100 商品”“每个类目销量前三”,MySQL 8.0 的 ROW_NUMBER() OVER(PARTITION BY category_id ORDER BY sales DESC) 写起来干净,但执行代价比 JOIN + 子查询高得多。
- 小结果集(
-
PARTITION BY字段必须有索引,否则会触发 filesort + temporary table,内存爆掉前先拖垮 QPS - 别在
ORDER BY里混用函数,比如ORDER BY UPPER(name),会导致窗口函数无法利用索引
真正卡住新项目的从来不是“有没有窗口函数”,而是认证连不上、INSERT 报错、JSON 查询慢到超时——这些坑在 8.0 里都得手动填,不能指望默认配置兜底。


















